/**************************************************************************** * (C) Tokyo Cosmos Electric, Inc. (TOCOS) - 2013 all rights reserved. * * Condition to use: * - The full or part of source code is limited to use for TWE (TOCOS * Wireless Engine) as compiled and flash programmed. * - The full or part of source code is prohibited to distribute without * permission from TOCOS. * ****************************************************************************/ // // KOG RC RXA00 (2.4GHz無線モジュールTWELITEを使ったRC受信機) // 2021/11/28 // 仕様 // プロポーショナル:サーボ信号出力 4ch // デジタル出力:8ch // // // #include // C 標準ライブラリ用 #include // NXP ペリフェラル API 用 #include "Master.h" #include "utils.h" // ペリフェラル API のラッパなど #include "serial.h" // シリアル用 #include "sprintf.h" // SPRINTF 用 #include "common.h" #include "eeprom_6x.h" /****************************************************************************/ /*** ToCoNet Definitions ***/ /****************************************************************************/ // Select Modules (define befor include "ToCoNet.h") #define ToCoNet_USE_MOD_ENERGYSCAN #define ToCoNet_USE_MOD_NBSCAN // Neighbour scan module #undef ToCoNet_USE_MOD_NBSCAN_SLAVE #include "ToCoNet.h" #include "ToCoNet_mod_prototype.h" // ToCoNet モジュール定義 //#define UART_BAUD 115200 // シリアルのボーレート // ToCoNet 用パラメータ #define RX_ID 0xABCDEF12 //APP_ID 任意の32bitデータ。送信機と合わせること。 #define RX_CH 11 //11~26まで設定可。 送信機と合わせること。 #define u8TxPower 3 static tsFILE sSerStream; // シリアル用ストリーム static tsSerialPortSetup sSerPort; // シリアルポートデスクリプタ static uint32 u32Seq; // 送信パケットのシーケンス番号 uint8 ad1; //ADC1のデータ uint8 rcv_buf[64]; //受信データ uint8 rcv_tmr = 50; //受信確認LED用 uint8 mctr=50; //モニタ出力間引き用 /****************************************************************************/ /*** Local Variables ***/ /****************************************************************************/ static tsAppData sAppData; //!< アプリケーションデータ @ingroup MASTER tsTimerContext sTimerApp; //!< タイマー管理構造体 @ingroup MASTER tsTimerContext sTimerPWM[4]; //!< タイマー管理構造体 @ingroup MASTER // デバッグ出力用に UART を初期化 static void vSerialInit() { static uint8 au8SerialTxBuffer[96]; static uint8 au8SerialRxBuffer[32]; sSerPort.pu8SerialRxQueueBuffer = au8SerialRxBuffer; sSerPort.pu8SerialTxQueueBuffer = au8SerialTxBuffer; sSerPort.u32BaudRate = UART_BAUD; sSerPort.u16AHI_UART_RTS_LOW = 0xffff; sSerPort.u16AHI_UART_RTS_HIGH = 0xffff; sSerPort.u16SerialRxQueueSize = sizeof(au8SerialRxBuffer); sSerPort.u16SerialTxQueueSize = sizeof(au8SerialTxBuffer); sSerPort.u8SerialPort = E_AHI_UART_0; sSerPort.u8RX_FIFO_LEVEL = E_AHI_UART_FIFO_LEVEL_1; SERIAL_vInit(&sSerPort); sSerStream.bPutChar = SERIAL_bTxChar; sSerStream.u8Device = E_AHI_UART_0; } //デジタル出力処理 void digi_out(unsigned char digi_data) { //digital output 1ch if(digi_data & 0x01) { vAHI_DioSetOutput(0x00000200 , 0x00000000); //set dio 9 } else { vAHI_DioSetOutput(0x00000000 , 0x00000200); //clear dio 9 } //digital output 2ch if(digi_data & 0x02) { vAHI_DioSetOutput(0x00000100 , 0x00000000); //set dio 8 } else { vAHI_DioSetOutput(0x00000000 , 0x00000100); //clear dio 8 } // digital output 3ch if(digi_data & 0x04) { vAHI_DioSetOutput(0x00000010 , 0x00000000); //set dio 4 } else { vAHI_DioSetOutput(0x00000000 , 0x00000010); //clear dio 4 } //digital output 4ch if(digi_data & 0x08) { vAHI_DioSetOutput(0x00080000 , 0x00000000); //set dio 19 } else { vAHI_DioSetOutput(0x00000000 , 0x00080000); //clear dio 19 } //digital output 5ch if(digi_data & 0x10) { vAHI_DioSetOutput(0x00040000 , 0x00000000); //set dio 18 } else { vAHI_DioSetOutput(0x00000000 , 0x00040000); //clear dio 18 } //digital output 6ch if(digi_data & 0x20) { vAHI_DioSetOutput(0x00000020 , 0x00000000); //set dio 5 } else { vAHI_DioSetOutput(0x00000000 , 0x00000020); //clear dio 5 } //digital output 7ch if(digi_data & 0x40) { vAHI_DioSetOutput(0x00004000 , 0x00000000); //set dio 14 } else { vAHI_DioSetOutput(0x00000000 , 0x00004000); //clear dio 14 } //digital output 8ch if(digi_data & 0x80) { vAHI_DioSetOutput(0x00000004 , 0x00000000); //set dio 02 } else { vAHI_DioSetOutput(0x00000000 , 0x00000004); //clear dio 02 } return; } //受け取ったADデータをサーボパルス幅信号に変換 uint16 get_pulse(uint16 adi) { uint16 ui16_1 , ui16_2; ui16_1=(1400*adi/1024)+800; //サーボ回転方向:ノーマルの場合 //ui16_1=(-1400*adi/1024)+2200; //サーボ回転方向:リバースの場合 ui16_2=ui16_1 & 0x00000FFF; return ui16_2; } // ユーザ定義のイベントハンドラ static void vProcessEvCore(tsEvent *pEv, teEvent eEvent, uint32 u32evarg) { uint8 ui8_0[25] , ui8_4[6]; uint8 ui8_1; int16 si16_2 , hdri , ch1i , ch2i , ch3i , ch4i , douti , csumi; // 起動時 (delay_time 2.5msec from cold start) if (eEvent == E_EVENT_START_UP) { vfPrintf(&sSerStream , "KOG RC RXA0 RX_CH=%d , APP_ID=%X\r\n" , RX_CH , RX_ID); } // 20ms 周期のシステムタイマ通知 if (eEvent == E_EVENT_TICK_TIMER) { strncpy(ui8_0,rcv_buf,24); //Headerの数値化処理 ui8_4[0]='0'; //0Xを付加 (0x頭にあると16進数と判断される) ui8_4[1]='x'; ui8_4[2]=ui8_0[0]; ui8_4[3]=ui8_0[1]; ui8_4[4]='\0'; hdri=strtoul(ui8_4,NULL,0); //16進文字列を整数に変換。 //ch1 pulseの数値化処理 ui8_4[2]=ui8_0[3]; ui8_4[3]=ui8_0[4]; ui8_4[4]=ui8_0[5]; ui8_4[5]='\0'; ch1i=strtoul(ui8_4,NULL,0); //16進文字列を整数に変換。 //ch2 pulseの数値化処理 ui8_4[2]=ui8_0[7]; ui8_4[3]=ui8_0[8]; ui8_4[4]=ui8_0[9]; ui8_4[5]='\0'; ch2i=strtoul(ui8_4,NULL,0); //16進文字列を整数に変換。 //ch3 pulseの数値化処理 ui8_4[2]=ui8_0[11]; ui8_4[3]=ui8_0[12]; ui8_4[4]=ui8_0[13]; ui8_4[5]='\0'; ch3i=strtoul(ui8_4,NULL,0); //16進文字列を整数に変換。 //ch4 pulseの数値化処理 ui8_4[2]=ui8_0[15]; ui8_4[3]=ui8_0[16]; ui8_4[4]=ui8_0[17]; ui8_4[5]='\0'; ch4i=strtoul(ui8_4,NULL,0); //16進文字列を整数に変換。 //digital outputの数値化処理 ui8_4[2]=ui8_0[19]; ui8_4[3]=ui8_0[20]; ui8_4[4]='\0'; douti=strtoul(ui8_4,NULL,0); //16進文字列を整数に変換。 //check sumの数値化処理 ui8_4[2]=ui8_0[22]; ui8_4[3]=ui8_0[23]; ui8_4[4]='\0'; csumi=strtoul(ui8_4,NULL,0); //16進文字列を整数に変換。 if((hdri==0xAA) && (((hdri+ch1i+ch2i+ch3i+ch4i+douti+csumi) & 0x00FF) == 0x00)) //Header & サム チェック { si16_2 = get_pulse(ch1i); //パルス幅に変換 vAHI_TimerStartSingleShot(E_AHI_TIMER_1,si16_2,30000); // TimerName , on_time , period si16_2 = get_pulse(ch2i); //パルス幅に変換 vAHI_TimerStartSingleShot(E_AHI_TIMER_2,si16_2,30000); // TimerName , on_time , period si16_2 = get_pulse(ch3i); //パルス幅に変換 vAHI_TimerStartSingleShot(E_AHI_TIMER_3,si16_2,30000); // TimerName , on_time , period si16_2 = get_pulse(ch4i); //パルス幅に変換 vAHI_TimerStartSingleShot(E_AHI_TIMER_4,si16_2,30000); // TimerName , on_time , period ui8_1=douti & 0x000000FF; //8bitデータに変換 digi_out(ui8_1); //デジタル出力処理 } if(rcv_tmr == 0) { vAHI_DioSetOutput(0x00000008, 0x00000000); //off LED } else { rcv_tmr = rcv_tmr -1; } mctr--; if(mctr == 0) //1sec間隔に間引いて実行 { mctr =50; //モニタ出力 vfPrintf(&sSerStream , "Hdr=%02X CH1=%03X CH2=%03X CH3=%03X CH4=%03X SW=%02X CSUM=%02X\r\n" , hdri , ch1i , ch2i , ch3i , ch4i , douti , csumi); //AD変換 (バッテリー電圧低下検出用。動力用モータがない場合は特に使用しない) vAHI_AdcEnable( E_AHI_ADC_SINGLE_SHOT , E_AHI_AP_INPUT_RANGE_2 , E_AHI_ADC_SRC_ADC_1); // set AD channel vAHI_AdcStartSample(); // ADC開始 vWait(100); ad1 = u16AHI_AdcRead(); // AD値の読み出し } } return; } void vProcessEvCorePwr(tsEvent *pEv, teEvent eEvent, uint32 u32evarg) { return; } void cbToCoNet_vNwkEvent(teEvent eEvent, uint32 u32arg) { return; } // // 以下 ToCoNet 既定のイベントハンドラ群 // // 割り込み発生後に随時呼び出される void cbToCoNet_vMain(void) { return; } // パケット受信時 void cbToCoNet_vRxEvent(tsRxDataApp *pRx) { static uint32 u32SrcAddrPrev = 0; static uint8 u8seqPrev = 0xFF; // 前回と同一の送信元+シーケンス番号のパケットなら受け流す if (pRx->u32SrcAddr == u32SrcAddrPrev && pRx->u8Seq == u8seqPrev) { return; } // ペイロードを切り出してデバッグ出力 //char buf[64]; int len = (pRx->u8Len < sizeof(rcv_buf)) ? pRx->u8Len : sizeof(rcv_buf)-1; memcpy(rcv_buf, pRx->auData, len); u32SrcAddrPrev = pRx->u32SrcAddr; u8seqPrev = pRx->u8Seq; vAHI_DioSetOutput(0x00000000, 0x00000008); //on LED(受信確認用) rcv_tmr = 50; //受信タイマ return; } // パケット送信完了時 void cbToCoNet_vTxEvent(uint8 u8CbId, uint8 bStatus) { return; } // ハードウェア割り込み発生後(遅延呼び出し) void cbToCoNet_vHwEvent(uint32 u32DeviceId, uint32 u32ItemBitmap) { return; } // ハードウェア割り込み発生時 uint8 cbToCoNet_u8HwInt(uint32 u32DeviceId, uint32 u32ItemBitmap) { return FALSE; } // コールドスタート時 void cbAppColdStart(bool_t bAfterAhiInit) { if (!bAfterAhiInit) { // 必要モジュール登録手続き ToCoNet_REG_MOD_ALL(); } else { // SPRINTF 初期化 SPRINTF_vInit128(); // ToCoNet パラメータ sToCoNet_AppContext.u32AppId = RX_ID; //APP_ID; sToCoNet_AppContext.u8Channel = RX_CH; //channel sToCoNet_AppContext.bRxOnIdle = TRUE; // アイドル時にも受信 sToCoNet_AppContext.u16TickHz = 50; //Tick timer 20msec u32Seq = 0; // ユーザ定義のイベントハンドラを登録 ToCoNet_Event_Register_State_Machine(vProcessEvCore); // ハードウェア初期化 // デバッグ出力用 vSerialInit(); ToCoNet_vDebugInit(&sSerStream); ToCoNet_vDebugLevel(0); // 使用ポートの設定 bAHI_DoEnableOutputs(FALSE); //output enable vAHI_DoSetDataOut(0x00 , 0x03); //set output data high , Low vAHI_DoSetPullup(0x03 , 0x00); //set do pullup enable , disable vAHI_DioSetOutput(0x00000008, 0x000ffff7); //set dio out high , low vAHI_DioSetDirection(0x00018083, 0x000e7f7c); //set dio directio inputport , outputport vAHI_DioSetPullup(0x00018083, 0x000e7f7c); //set dio pullup enable , disable //ADCの設定 if (!bAHI_APRegulatorEnabled()) { vAHI_ApConfigure(E_AHI_AP_REGULATOR_ENABLE, E_AHI_AP_INT_ENABLE, // DISABLE にするとアナログ部の電源断 E_AHI_AP_SAMPLE_2, // サンプル数 2,4,6,8 が選択可能 E_AHI_AP_CLOCKDIV_500KHZ, // 周波数 250K/500K/1M/2M E_AHI_AP_INTREF); while(!bAHI_APRegulatorEnabled()); // 安定するまで待つ } //PWMの設定 //pwm 1 vAHI_TimerEnable(E_AHI_TIMER_1,4,FALSE,FALSE,TRUE); //tinerName , プリスケーラ(2^n) , timer_int(rise) , timer_int(down) ,pwm_mode vAHI_TimerDIOControl(E_AHI_TIMER_1,TRUE); //timerName , pwm_out vAHI_TimerConfigureOutputs(E_AHI_TIMER_1,TRUE,TRUE); //出力パルス:正。 第2パラメータをFALSEにすると出力パルスは負になる。 vAHI_TimerClockSelect(E_AHI_TIMER_1,FALSE,TRUE); // TimerName , ex_clock_sorce , clock_out_invert //pwm 2 vAHI_TimerEnable(E_AHI_TIMER_2,4,FALSE,FALSE,TRUE); //tinerName , プリスケーラ(2^n) , timer_int(rise) , timer_int(down) ,pwm_mode vAHI_TimerDIOControl(E_AHI_TIMER_2,TRUE); //timerName , pwm_out vAHI_TimerConfigureOutputs(E_AHI_TIMER_2,TRUE,TRUE); //出力パルス:正。 第2パラメータをFALSEにすると出力パルスは負になる。 vAHI_TimerClockSelect(E_AHI_TIMER_2,FALSE,TRUE); // TimerName , ex_clock_sorce , clock_out_invert //pwm 3 vAHI_TimerEnable(E_AHI_TIMER_3,4,FALSE,FALSE,TRUE); //tinerName , プリスケーラ(2^n) , timer_int(rise) , timer_int(down) ,pwm_mode vAHI_TimerDIOControl(E_AHI_TIMER_3,TRUE); //timerName , pwm_out vAHI_TimerConfigureOutputs(E_AHI_TIMER_3,TRUE,TRUE); //出力パルス:正。 第2パラメータをFALSEにすると出力パルスは負になる。 vAHI_TimerClockSelect(E_AHI_TIMER_3,FALSE,TRUE); // TimerName , ex_clock_sorce , clock_out_invert //pwm 4 vAHI_TimerEnable(E_AHI_TIMER_4,4,FALSE,FALSE,TRUE); //tinerName , プリスケーラ(2^n) , timer_int(rise) , timer_int(down) ,pwm_mode vAHI_TimerDIOControl(E_AHI_TIMER_4,TRUE); //timerName , pwm_out vAHI_TimerConfigureOutputs(E_AHI_TIMER_4,TRUE,TRUE); //出力パルス:正。 第2パラメータをFALSEにすると出力パルスは負になる。 vAHI_TimerClockSelect(E_AHI_TIMER_4,FALSE,TRUE); // TimerName , ex_clock_sorce , clock_out_invert // MAC 層開始 ToCoNet_vMacStart(); } } // ウォームスタート時 void cbAppWarmStart(bool_t bAfterAhiInit) { return; }