/**************************************************************************** * (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 TXA00 (2.4GHz無線モジュールTWELITEを使ったRC送信機) // 2021/11/27 // 仕様 // プロポーショナル:4ch // デジタル出力:8ch // 電源:LiPo 1cell(3.7V) or NiMH 3cell(3.6V) or 乾電池3本(4.5V) // // #include // C 標準ライブラリ用 #include // NXP ペリフェラル API 用 #include "utils.h" // ペリフェラル API のラッパなど #include "serial.h" // シリアル用 #include "sprintf.h" // SPRINTF 用 #include "common.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 TX_CH 11 //freqency channel (11から26まで設定可。受信機側と合わせる必要あり。) #define TX_ID 0xABCDEF12 //受信機側と合わせる必要あり。 #define Header 0xAA static tsFILE sSerStream; // シリアル用ストリーム static tsSerialPortSetup sSerPort; // シリアルポートデスクリプタ static uint32 u32Seq; // 送信パケットのシーケンス番号。任意に設定可能.重複パケットの判定などに使用. uint16 ad1=511; //AD変換値 (CH1) uint16 ad2=511; //AD変換値 (CH2) uint16 ad3=511; //AD変換値 (CH3) uint16 ad4=511; //AD変換値 (CH4) uint8 sw = 0x00; //digital SW input uint8 csum; //チェックサム uint8 mctr=250; //モニタ出力間引き用 // デバッグ出力用に UART を初期化 static void vSerialInit() { static uint8 au8SerialTxBuffer[96]; static uint8 au8SerialRxBuffer[32]; sSerPort.pu8SerialRxQueueBuffer = au8SerialRxBuffer; sSerPort.pu8SerialTxQueueBuffer = au8SerialTxBuffer; sSerPort.u32BaudRate = 115200; // シリアルのボーレート 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; } //8chデジタル入力 uint8 get_sw_input(void) { uint8 sw_input = 0x00; uint32 Dio_input_data; sw_input = 0x00; Dio_input_data = u32AHI_DioReadInput() ^ 0xffffffff; if(Dio_input_data & 0x00000200) //ch 1? { sw_input = sw_input | 0x01; } if(Dio_input_data & 0x00000100) //ch 2? { sw_input = sw_input | 0x02; } if(Dio_input_data & 0x00000010) //ch 3? { sw_input = sw_input | 0x04; } if(Dio_input_data & 0x00080000) //ch 4? { sw_input = sw_input | 0x08; } if(Dio_input_data & 0x00040000) //ch 5? { sw_input = sw_input | 0x10; } if(Dio_input_data & 0x00000020) //ch 6? { sw_input = sw_input | 0x20; } if(Dio_input_data & 0x00004000) //ch 7? { sw_input = sw_input | 0x40; } if(Dio_input_data & 0x00000004) //ch 8? { sw_input = sw_input | 0x80; } return sw_input; } // ブロードキャスト実行 static bool_t sendBroadcast () { tsTxDataApp tsTx; memset(&tsTx, 0, sizeof(tsTxDataApp)); tsTx.u32SrcAddr = ToCoNet_u32GetSerial(); //モジュールシリアル番号 tsTx.u32DstAddr = TOCONET_MAC_ADDR_BROADCAST; //宛先アドレス。 tsTx.bAckReq = FALSE; //ACKなし tsTx.u8Retry = 0x80; // 1回送信。3回の場合は0x82。 tsTx.u8CbId = u32Seq & 0x000000FF; // TxEvent で通知される番号、送信先には通知されない tsTx.u8Seq = u32Seq & 0x000000FF; // シーケンス番号(送信先に通知される) tsTx.u8Cmd = TOCONET_PACKET_CMD_APP_DATA; //パケット種別。 // SPRINTF でペイロードを作成 SPRINTF_vRewind(); //バッファを先頭に巻き戻す。 vfPrintf(SPRINTF_Stream, "%01X %03X %03X %03X %03X %02X %02X" , Header , ad1 , ad2 , ad3 , ad4 , sw , csum); memcpy(tsTx.auData, SPRINTF_pu8GetBuff(), SPRINTF_u16Length()); //コピー先のメモリブロックのポインタ, コピー元のメモリブロックのポインタ(SPRINTF_pu8GetBuff()は先頭アドレスの取得), コピーサイズ tsTx.u8Len = SPRINTF_u16Length(); //パケット長 u32Seq++; // 送信パケットのシーケンス番号 // 送信 return ToCoNet_bMacTxReq(&tsTx); } // ユーザ定義のイベントハンドラ static void vProcessEvCore(tsEvent *pEv, teEvent eEvent, uint32 u32evarg) { // 起動時 if (eEvent == E_EVENT_START_UP) { vfPrintf(&sSerStream , "KOG RC TXA0 TX_CH=%d TX_ID=%08X\r\n" ,TX_CH , TX_ID); } // 4ms 周期のシステムタイマ通知 if (eEvent == E_EVENT_TICK_TIMER) { uint16 temp; //ad_con start 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); //70usec wait ad1 = u16AHI_AdcRead(); // AD値の読み出し vAHI_AdcEnable(E_AHI_ADC_SINGLE_SHOT , E_AHI_AP_INPUT_RANGE_2 , E_AHI_ADC_SRC_ADC_2); // set AD channel vAHI_AdcStartSample(); // ADC開始 vWait(100); //70usec wait ad2 = u16AHI_AdcRead(); // AD値の読み出し vAHI_AdcEnable(E_AHI_ADC_SINGLE_SHOT , E_AHI_AP_INPUT_RANGE_2 , E_AHI_ADC_SRC_ADC_3); // set AD channel vAHI_AdcStartSample(); // ADC開始 vWait(100); //70usec wait ad3 = u16AHI_AdcRead(); // AD値の読み出し vAHI_AdcEnable(E_AHI_ADC_SINGLE_SHOT , E_AHI_AP_INPUT_RANGE_2 , E_AHI_ADC_SRC_ADC_4); // set AD channel vAHI_AdcStartSample(); // ADC開始 vWait(100); //70usec wait ad4 = u16AHI_AdcRead(); // AD値の読み出し sw = get_sw_input(); temp = Header+ad1+ad2+ad3+ad4+sw; //チェックサムの計算 csum = ((temp & 0x00FF) ^ 0xFF) + 1; sendBroadcast(); //送信 mctr--; if(mctr == 0) //1sec間隔に間引いて表示 { mctr =250; //モニタ出力 vfPrintf(&sSerStream , "Hdr=%01X AD1=%03X AD2=%03X AD3=%03X AD4=%03X SW=%02X CSUM=%02X\r\n" , Header , ad1 , ad2 , ad3 , ad4 , sw , csum); } } // 1s 周期のシステムタイマ通知 if (eEvent == E_EVENT_TICK_SECOND) { if(u8AHI_ComparatorStatus() == 0) //バッテリー電圧低下モニタLED用 { //vAHI_TimerDIOControl(E_AHI_TIMER_2,TRUE); //timerName , pwm_out (LED点滅) vAHI_TimerStartSingleShot(E_AHI_TIMER_2,7800,30000); //(LED点滅) } else { //vAHI_TimerDIOControl(E_AHI_TIMER_2,FALSE); //timerName , pwm_out (LED点灯) vAHI_TimerStartSingleShot(E_AHI_TIMER_2,20000,30000); //(LED点灯) } } 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) { 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 = TX_ID; //APP_ID sToCoNet_AppContext.u8Channel = TX_CH; //CHANNEL sToCoNet_AppContext.u8TxPower = 3; //max power sToCoNet_AppContext.bRxOnIdle = TRUE; // アイドル時にも受信 sToCoNet_AppContext.u16TickHz = 250; //4msec 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(0x00001000, 0x000fefff); //set dio out high , low vAHI_DioSetDirection(0x000fefbf, 0x00001040); //set dio directio inputport , outputport vAHI_DioSetPullup(0x000eefbc, 0x00011043); //set dio pullup enable , disable // ADCを利用するには3つの手続きが必要です。 1) アナログ部の電源投入 2) ADC 開始 3) 完了待ちおよび読み出し となります。 // 1) アナログ部の電源投入 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_1MHZ // 周波数 250K/500K/1M/2M ,E_AHI_AP_INTREF); //内部refarence while(!bAHI_APRegulatorEnabled()); // 安定するまで待つ } //コンパレータの設定 vAHI_ComparatorEnable(E_AHI_AP_COMPARATOR_1,E_AHI_COMP_HYSTERESIS_20MV,E_AHI_COMP_SEL_BANDGAP); vAHI_ComparatorIntEnable(E_AHI_AP_COMPARATOR_1,FALSE,FALSE); //Identity of comparator,interrupts, TRUE:rise/FALSE:fall //Timer2バッテリーモニタLEDブリンク用 vAHI_TimerEnable(E_AHI_TIMER_2,10,FALSE,FALSE,TRUE); //tinerName , プリスケーラ(2^n n:0_16) , timer_int(rise) , timer_int(down) ,pwm_mode vAHI_TimerDIOControl(E_AHI_TIMER_2,TRUE); //timerName , pwm_out禁止 vAHI_TimerConfigureOutputs(E_AHI_TIMER_2,FALSE,TRUE); //TimerName , inversion , ex_input vAHI_TimerClockSelect(E_AHI_TIMER_2,FALSE,TRUE); //TimerName , ex_clock_sorce , clock_out_invert vAHI_TimerStartSingleShot(E_AHI_TIMER_2,20000,30000); //TimerName , on_time , period (LED点滅) ToCoNet_vMacStart(); // MAC 層開始 } } // ウォームスタート時 void cbAppWarmStart(bool_t bAfterAhiInit) { return; }