//**************************************************************** // // 簡易送受信チップ・ファームウェア // // Ver.040811 by K.I // //**************************************************************** #define SYSCLOCK 10000000 //10MHz or 20MHz #define HAMMING //Hamming decode ON #include <16f877.h> #fuses HS,NOWDT,NOPROTECT,PUT,NOBROWNOUT,NOLVP #use delay(clock=SYSCLOCK) #use RS232(BAUD=9600,XMIT=PIN_C6,RCV=PIN_C7) #use fast_io(A) #use fast_io(B) #use fast_io(C) #use fast_io(D) #if SYSCLOCK == 10000000 #define NOISE 0xE0 #define EDGE_BIT 2 #define CLK50MS 961 #endif #if SYSCLOCK == 20000000 #define NOISE 0xF0 #define EDGE_BIT 3 #define CLK50MS 1923 #endif // ---- 多byteデータアクセス用共用体 -------- union buf16 { int16 longbuf; int8 buf[2]; }; union buf32 { int32 longbuf; int8 buf[4]; }; // ---- PIN設定 -------- #define TXD pin_c5 #define RXD pin_a3 #define XSTART pin_e1 #define RXE pin_a5 #define TXE pin_e0 #define SEND pin_a1 #define TX_RX pin_a2 #define OPR pin_e2 #define RANDOM pin_c0 #define PLL_DATA pin_c1 #define PLL_CLK pin_c2 #define PLL_LE pin_c3 #define XXX pin_a4 #define STB pin_a0 #define LD pin_c4 #define SWIN input_b() #define LEDOUT output_d #define LEDIN input_d() // ---- タイマ0プリセット値(基本クロック設定) -------- #define T0PRESET -95 //-95:(10MHz時→約52us,20MHz時→約26us) // ---- フレームヘッダ -------- #define FRAMEHEAD1 0b11110001 #define FRAMEHEAD2 0b00110101 // ---- PLL 設定値 -------- #define TXR 0x082051 //送信 #define TXN 0x852830 //#define TXN 0x85282C // Level down #define RXR 0x082051 //受信 #define RXN 0x850430 #define OFFR 0x082011 //OFF(スタンバイ) #define OFFN 0x850430 #define PLL_RX 0 #define PLL_TX 1 #define PLL_OFF 2 #define PLL_NONE 3 // ---- PN符号発生用 -------- #define PN_TAP 0x0011 //511PN用タップ #define PN_STAGE 0x01ff //9bitマスク // ---- テーブル -------- #if SYSCLOCK == 10000000 int8 const version[] = "sdtc v.040929-10M-30 by K.I NPC"; #endif #if SYSCLOCK == 20000000 int8 const version[] = "sdtc v.040929-20M-30 by K.I NPC"; #endif int8 const hamming_encode[16] = { 0x00,0x1e,0x2d,0x33,0x4b,0x55,0x66,0x78, 0x87,0x99,0xaa,0xb4,0xcc,0xd2,0xe1,0xff }; int8 const hamming_decode[128] = { 0x00,0x00,0x00,0x43,0x00,0x25,0x16,0x0F, 0x00,0x19,0x2A,0x0F,0x4C,0x0F,0x0F,0x0F, 0x00,0x19,0x16,0x33,0x16,0x55,0x16,0x16, 0x19,0x19,0x5A,0x19,0x3C,0x19,0x16,0x0F, 0x00,0x25,0x2A,0x33,0x25,0x25,0x66,0x25, 0x2A,0x69,0x2A,0x2A,0x3C,0x25,0x2A,0x0F, 0x70,0x33,0x33,0x33,0x3C,0x25,0x16,0x33, 0x3C,0x19,0x2A,0x33,0x3C,0x3C,0x3C,0x7F, 0x00,0x43,0x43,0x43,0x4C,0x55,0x66,0x43, 0x4C,0x69,0x5A,0x43,0x4C,0x4C,0x4C,0x0F, 0x70,0x55,0x5A,0x43,0x55,0x55,0x16,0x55, 0x5A,0x19,0x5A,0x5A,0x4C,0x55,0x5A,0x7F, 0x70,0x69,0x66,0x43,0x66,0x25,0x66,0x66, 0x69,0x69,0x2A,0x69,0x4C,0x69,0x66,0x7F, 0x70,0x70,0x70,0x33,0x70,0x55,0x66,0x7F, 0x70,0x69,0x5A,0x7F,0x3C,0x7F,0x7F,0x7F }; // ---- Global変数 --------- int16 tx_clk; int16 rx_clk; int8 rx_edge; int8 rx_count; int8 tx_count; union buf16 rx_buf; int8 rx_bufx; int8 rx_data,rx_last; union buf32 rx_data0,rx_data1; int1 test_mode=0; int8 pll_mode=PLL_NONE; int16 pn_data=0xffff; int8 rcv_hamming(hdata,ldata) { int8 rdata; #ifdef HAMMING rdata = hamming_decode[hdata>>1]>>3<<4; //上位4bit rdata += hamming_decode[ldata>>1]>>3; //下位4bit #else rdata = hdata>>4<<4; //上位4bit rdata += ldata>>4; //下位4bit #endif return(rdata); } // ---- タイマ0割込みルーチン -------- #INT_RTCC void rtcc_isr(){ //output_high(STB); set_timer0(T0PRESET); //タイマプリセット tx_clk++; rx_clk++; // ---- データ→受信バッファ -------- rx_buf.longbuf >>= 1; if (input(RXD)) bit_set(rx_buf.longbuf,15); else bit_clear(rx_buf.longbuf,15); //output_low(STB); // ---- ノイズ除去回路 -------- rx_bufx = rx_buf.buf[1]&NOISE; if (!rx_bufx) //3-4bit連続0→0 bit_clear(rx_buf.buf[1],1); else if (rx_bufx==NOISE) //3-4bit連続1→1 bit_set(rx_buf.buf[1],1); else if (bit_test(rx_buf.buf[1],0)) //それ以外は前回の状態を保つ bit_set(rx_buf.buf[1],1); else bit_clear(rx_buf.buf[1],1); // ---- 同期検出回路 -------- #if SYSCLOCK == 20000000 if (rx_buf.buf[0]==0xf0) { //0→1 rx_edge = rx_clk&0x07; goto rx_0; } else if (rx_buf.buf[0]==0x0f) { //1→0 rx_edge = rx_clk&0x07; goto rx_1; } else if (rx_buf.buf[0]==0x00) { //0→0 if ((rx_clk&0x07)==rx_edge) { goto rx_0; } } else if (rx_buf.buf[0]==0xff) { //1→1 if ((rx_clk&0x07)==rx_edge) { goto rx_1; } } goto rx_end; #endif #if SYSCLOCK == 10000000 rx_bufx = rx_buf.buf[0] & 0x7E; if (rx_bufx==0x70) { //0→1 rx_edge = rx_clk&0x03; goto rx_0; } else if (rx_bufx==0x0E) { //1→0 rx_edge = rx_clk&0x03; goto rx_1; } else if (rx_bufx==0x00) { //0→0 if ((rx_clk&0x03)==rx_edge) { goto rx_0; } } else if (rx_bufx==0x7E) { //1→1 if ((rx_clk&0x03)==rx_edge) { goto rx_1; } } goto rx_end; #endif rx_0: //output_high(STB); if (bit_test(rx_count++,0)) { rx_data0.longbuf <<= 1; //rx_data0をシフト bit_clear(rx_data0.longbuf,0); //データ0 goto data0_check; } else { rx_data1.longbuf <<= 1; //rx_data1をシフト bit_clear(rx_data1.longbuf,0); //データ0 goto data1_check; } goto rx_end; rx_1: //output_high(STB); if (bit_test(rx_count++,0)) { rx_data0.longbuf <<= 1; //rx_data0をシフト bit_set(rx_data0.longbuf,0); //データ1 goto data0_check; } else { rx_data1.longbuf <<= 1; //rx_data1をシフト bit_set(rx_data1.longbuf,0); //データ1 goto data1_check; } goto rx_end; data0_check: if (rx_data0.buf[3]==FRAMEHEAD1) { //ヘッダチェック if (rx_data0.buf[0]==FRAMEHEAD2) { rx_data = rcv_hamming(rx_data0.buf[2],rx_data0.buf[1]); if (rx_data==rx_last) { LEDOUT(rx_data); rx_clk=0; } rx_last = rx_data; } } goto rx_end; data1_check: if (rx_data1.buf[3]==FRAMEHEAD1) { //ヘッダチェック if (rx_data1.buf[0]==FRAMEHEAD2) { rx_data = rcv_hamming(rx_data1.buf[2],rx_data1.buf[1]); if (rx_data==rx_last) { LEDOUT(rx_data); rx_clk=0; } rx_last = rx_data; } } goto rx_end; rx_end: ; //output_low(STB); } void pll_wait_clk() //クロック待ち { while(!bit_test(tx_clk,0)) ; while(bit_test(tx_clk,0)) ; } void pll_clk_one() //PLL設定用CLKを1回出力 { while(!bit_test(tx_clk,0)) ; output_bit(PLL_CLK,1); while(bit_test(tx_clk,0)) ; output_bit(PLL_CLK,0); } void pll_le_one() //PLL設定用LEを1回出力 { while(!bit_test(tx_clk,0)) ; output_bit(PLL_LE,1); while(bit_test(tx_clk,0)) ; output_bit(PLL_LE,0); } void pll_set_data(int32 data) //PLL設定 { int8 i; pll_wait_clk(); for (i=0; i<24 ;i++) { //24bit設定 if (bit_test(data,23)) output_bit(PLL_DATA,1); //send '1' else output_bit(PLL_DATA,0); //send '0' pll_clk_one(); data <<= 1; } pll_le_one(); } int8 setup_pll(int8 mode) { if (mode == pll_mode) return(0); //モード変更なし→戻る pll_mode = mode; if (pll_mode==PLL_RX) { //RX mode output_bit(TXE,0); output_bit(RXE,1); pll_set_data(RXR); pll_set_data(RXN); } else if (pll_mode==PLL_TX) { //TX mode output_bit(RXE,0); output_bit(TXE,1); pll_set_data(TXR); pll_set_data(TXN); } else { output_bit(TXE,0); output_bit(RXE,0); pll_set_data(OFFR); //PLL off pll_set_data(OFFN); } } // ---- I/Oポート初期設定 -------- void setup_port() { byte data; set_tris_A(0b00001110); set_tris_B(0b11111111); //swin set_tris_C(0b10010001); set_tris_D(0b00000000); //ledout output_a(0); output_c(0); output_d(0); if(!input(RANDOM)) { //test mode test_mode = 1; data = 1; while(data) { LEDOUT(data); delay_ms(100); data <<= 1; } LEDOUT(data); } else { //normal mode LEDOUT(0x55); delay_ms(100); LEDOUT(0xaa); delay_ms(100); LEDOUT(0x55); delay_ms(100); LEDOUT(0xaa); delay_ms(100); LEDOUT(0x00); } output_bit(XSTART,1); //X'tal起動設定ON printf("%s\n",version); } void setup_interrupt() //割込み初期設定 { setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1); set_timer0(T0PRESET); enable_interrupts(INT_TIMER0); enable_interrupts(GLOBAL); } // ---- PN符号ジェネレータ -------- int16 pn9(int16 data, int16 tap) { int mask,line,i; data = data & PN_STAGE; mask = data & tap; line = 0; for (i=0; i<9 ;i++) { line += mask & 0x01; mask = mask>>1; } data = data<<1; if (line & 0x01) { data = data|1; } return(data&PN_STAGE); } void send_1() //1出力(TXDを0に戻すのに使用) { while(!bit_test(tx_clk,EDGE_BIT)) ; output_bit(TXD,1); while(bit_test(tx_clk,EDGE_BIT)) ; output_bit(TXD,0); } void send_bit7(byte data) //dataのbit7のみ出力 { if (bit_test(data,7)) { //send '1' while(!bit_test(tx_clk,EDGE_BIT)) ; output_bit(TXD,1); while(bit_test(tx_clk,EDGE_BIT)) ; output_bit(TXD,0); } else { //send '0' while(!bit_test(tx_clk,EDGE_BIT)) ; output_bit(TXD,0); while(bit_test(tx_clk,EDGE_BIT)) ; output_bit(TXD,1); } } void send_data(byte data) //8ビットデータ送信 { byte i; for (i=0; i<8 ;i++) { //1ビット×8送信 send_bit7(data); data <<= 1; } } void send_hamming(byte data) { swap(data); send_data(hamming_encode[data&0x0f]); //上位4bit送信 swap(data); send_data(hamming_encode[data&0x0f]); //下位4bit送信 } void trig_stb() { while(!bit_test(tx_clk,EDGE_BIT)) ; //トリガ用パルス生成 output_high(STB); while(bit_test(tx_clk,EDGE_BIT)) ; output_low(STB); } void out_stb() { if (bit_test(rx_buf.buf[0],0)) //rx_bufを出力 // if (bit_test(rx_data0.longbuf,0)) //rx_data0を出力 output_high(STB); //STB端子に出力 else output_low(STB); } //void pn_mode() //PN符号出力モード //{ // int8 data; // // while(!input(RANDOM)) { //RANDOMキーが押されていたら // setup_pll(PLL_TX); //PLL TX設定 // pn_data = pn9(pn_data,PN_TAP); // send_bit7(pn_data); // } //} //--PN符号ジェネレータによる511PN出力が何故かうまくいかないため、 //--データをすべて列挙する方法にした。(但し最初に1が多いので512bitになっている) void pn_mode() //PN符号出力モード { while(!input(RANDOM)) { //RANDOMキーが押されていたら setup_pll(PLL_TX); //PLL TX設定 send_data(0b10000011); //(最初の1は本当は不要) send_data(0b11011111); send_data(0b00010111); send_data(0b00110010); send_data(0b00001001); send_data(0b01001110); send_data(0b11010001); send_data(0b11100111); send_data(0b11001101); send_data(0b10001010); send_data(0b10010001); send_data(0b11000110); send_data(0b11010101); send_data(0b11000100); send_data(0b11000100); send_data(0b01000000); send_data(0b00100001); send_data(0b00011000); send_data(0b01001110); send_data(0b01010101); send_data(0b10000110); send_data(0b11110100); send_data(0b11011100); send_data(0b10001010); send_data(0b00010101); send_data(0b10100111); send_data(0b11101100); send_data(0b10010010); send_data(0b11011111); send_data(0b10010011); send_data(0b01010011); send_data(0b00110000); send_data(0b00011000); send_data(0b11001010); send_data(0b00110100); send_data(0b10111111); send_data(0b10100010); send_data(0b11000111); send_data(0b01011001); send_data(0b01100111); send_data(0b10001111); send_data(0b10111010); send_data(0b00001101); send_data(0b01101101); send_data(0b11011000); send_data(0b00101101); send_data(0b01111101); send_data(0b01010100); send_data(0b00001010); send_data(0b01010111); send_data(0b10010111); send_data(0b01110000); send_data(0b00111001); send_data(0b11010010); send_data(0b01111010); send_data(0b11101010); send_data(0b00100100); send_data(0b00110011); send_data(0b10000101); send_data(0b11101101); send_data(0b10011010); send_data(0b00011101); send_data(0b11100001); send_data(0b11111111); if (rx_clk>CLK50MS) LEDOUT(0); //LED消灯 } } void tx_mode() //送信モード { if (!input(SEND)) { setup_pll(PLL_TX); //PLL TX設定 tx_count=0; while(!input(SEND)) { //送信キーが押されていたら tx_clk = 0; trig_stb(); //STBにトリガ出力 send_data(0xff); //ヘッダFF出力 send_data(FRAMEHEAD1); //ヘッダ1出力 send_hamming(SWIN); //データ出力 send_data(FRAMEHEAD2); //ヘッダ2出力 send_1(); //出力を0に戻す while(tx_clk=90) break; ///4.5秒間データ送信 } if (rx_clk>CLK50MS) LEDOUT(0); //LED消灯 } if (!test_mode) { setup_pll(PLL_RX); //PLL OFF設定 tx_count=0; while(TRUE) { tx_clk = 0; while(tx_clk=50) break; //2.5秒間無送信 if (rx_clk>CLK50MS) LEDOUT(0); //LED消灯 } } } } void rx_mode() //受信モード //data0、data1バッファのいずれかのデータを受信データとする { out_stb(); //STB出力 setup_pll(PLL_RX); //PLL RX設定 } void main() { setup_port(); //ポート初期設定 setup_interrupt(); //割込み初期設定 while(TRUE) { while (!input(OPR)) { setup_pll(PLL_OFF); //OPRが0なら強制的にOFF output_bit(XSTART,0); //X'tal起動設定OFF } output_bit(XSTART,1); //X'tal起動設定ON if (rx_clk>CLK50MS) LEDOUT(0); //LED消灯 if (input(TX_RX)) { //TX_RXが1で if (test_mode) { //テストモードなら setup_pll(PLL_TX); //キャリアを出し続ける } } else if (!input(TX_RX)) { //TX_RXが0なら受信モードに rx_mode(); //(キャリア停止) } tx_mode(); //送信モード pn_mode(); //PNモード } }