// transceiver firmware version 8 // // Jan. 28, 2006 // //**************************************************** // // main polling loop // incoming packet? // time to send a ping? // communication failure? // give up on ACK? // // payload types // data only // ack // ack & data // ping // pong // payload contents // 0 user data 1 // 1 user data 2 // 2 user data 3 // 3 high nibble: payload type, low nibble: number of user bytes // 4 sequence number (used when sending user data) // 5 sequence number (used when acknowedging user data) //**************************************************** #include <16F628.h> #device adc=8 #use delay(clock=4000000) #fuses PUT, XT, NOMCLR, NOWDT, NOLVP, NOBROWNOUT, NOPROTECT #use rs232(baud=9600,parity=N,xmit=PIN_B2,rcv=PIN_B1,bits=8) //#use fast_io(B) #define DEBUG 1 #define STATUS_LIGHT PIN_A2 // --------------------- // Port B // --------------------- //#define TRW_CLK2 PIN_B0 // #define TRW_CLK1 PIN_B5 // #define TRW_CS PIN_B7 // #define TRW_CE PIN_B3 // //#define TRW_DOUT2 PIN_B4 // #define TRW_DATA PIN_B4 // #define TRW_DR1 PIN_B6 // //#define TRW_DR2 PIN_B7 // // 0-out 1-in 0b76543210 #define B_TRIS 0b11110000 //#define B_TRIS 0b01000111 inline initPorts() { port_b_pullups(FALSE); disable_interrupts(INT_RB); } // ======================================================================== // TRW interface // // - 2 byte address // - 6 byte payload // - 2 byte crc // -- //byte 14 set to # bits in data payload #define DATA2_W 48 // original //byte 13 set to # bits in data payload #define DATA1_W 48 // original //byte 12-8 40 bit address #define ADDR2_4 0x00 #define ADDR2_3 0x00 #define ADDR2_2 0x00 #define ADDR2_1 0x42 #define ADDR2_0 0x42 //byte 7-3 40 bit address #define ADDR1_4 0x00 #define ADDR1_3 0x00 #define ADDR1_2 0x00 #define ADDR1_1 0x42 #define ADDR1_0 0x42 //byte 2 bit 7-2 # address bits // bit 1 0-8bit 1-16bit crc size // bit 0 1-Enable CRC // 0b76543210 #define ADDR_W 0b01000000 #define CRC_L 0b00000010 #define CRC_EN 0b00000001 //#define CRC_EN 0b00000000 // I turned crc off for testing purposes //byte 1 bit 7 1-Enable dual channel // bit 6 1-Enable shockburst // bit 5 1-Enable 1mb/s // bit 4-2 Crystal freq 011-16MHz // bit 1-0 Power: 11-max power // 0b76543210 #define RX2_EN 0b10000000 #define CM 0b01000000 //I disabled 1mb/s on Jan. 1, 2006 and performance increased dramaticly //#define RFDR_SB 0b00100000 // 1mb/s #define RFDR_SB 0b00000000 // 250kb/s #define XO_F 0b00001100 //#define RF_PWR 0b00000000 // -20db //#define RF_PWR 0b00000001 // -10db (what Ron was using) //#define RF_PWR 0b00000010 // -5db #define RF_PWR 0b00000011 // 0db (full power) //byte 0 bit 7-1 Channel 0b11111000 seems to be max // bit 0 1-Rx Enable // 0b76543210 #define RF_CH 0b11110110 // channel 123 2,523MHz #define RXEN 0b00000001 #define PAYLOAD_MAX 6 byte payload[PAYLOAD_MAX]; #define CLKDELAY() //delay_us(5) #define CSDELAY() //delay_us(10) #define PWUPDELAY() delay_us(999) #define BUFFER_SIZE 32 // RF transmit buffer // packet types #define USER_DATA 1 #define ACK 2 #define ACK_AND_DATA 3 #define PING 4 #define PONG 5 #define AND && #define OR || // rs232 transmit buffer //#define T_BUFFER_SIZE 16 #define T_BUFFER_SIZE 64 byte t_buffer[T_BUFFER_SIZE]; byte t_next_in = 0; byte t_next_out = 0; int8 x, z; // rf transmit buffer int8 q[BUFFER_SIZE]; int8 q_in; // add pointer int8 q_out; // take pointer int8 k; // int8 unsent_bytes; int1 WAITING_FOR_ACK; int1 WAITING_FOR_PONG; int1 NEED_TO_SEND_ACK; int1 NEED_TO_RESEND_DATA; int8 number_of_user_bytes_in; // 1 to 3 int8 number_of_outgoing_user_bytes; // 1 to 3 int8 payload_type; int8 outgoing_sequence_number = 0; int8 expected_sequence_number = 0; int32 current_time = 0; int32 time_last_packet_sent = 0; int32 time_last_packet_received = 0; int32 time_last_user_data_sent = 0; int32 time_waiting_for_ack = 0; //int32 time1, time2, time3, time4, time22, time24, time25, time26; void trwConfig(void); void trwSetRx(void); void trwSetTx(void); void putBuf(void); void getBuf(void); char get_from_buffer(void); char user[3]; void init(void); void try_to_connect(void); // returns when connected void handle_io(void); // returns only if connection is lost void send_user_data(void); void receive_and_process(void); void assemble_and_send_packet(void); void rf_transmit_data(void); void get_data_from_uart_if_any(void); void bputc(char); // buffered putc // ======================================================================== // // MAIN // main(){ init(); while(1){ try_to_connect(); // returns when connected output_low(STATUS_LIGHT); // (ON) if(DEBUG) printf("*link established*\r\n"); handle_io(); // returns only if connection is lost // give up for a while output_high(STATUS_LIGHT); // (OFF) if(DEBUG) printf("*link lost*\r\n"); delay_ms(800); } } //-------------------------------------- void init() { trwConfig(); trwSetRx(); // switch to receive delay_ms(1); port_b_pullups(TRUE); //setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1|RTCC_8_BIT); setup_timer_2(T2_DIV_BY_4,16,16); // interupts every 1.024ms if(DEBUG) printf( "RF version 8\r\n" ); output_low(STATUS_LIGHT); // (ON) delay_ms(200); output_high(STATUS_LIGHT); // (OFF) delay_ms(200); output_low(STATUS_LIGHT); // (ON) delay_ms(200); output_high(STATUS_LIGHT); // (OFF) delay_ms(200); q_in = 0; q_out = 0; k = 0; unsent_bytes = 0; enable_interrupts(global); enable_interrupts(int_rda); enable_interrupts(int_timer2); } //----------- void try_to_connect() { while(1){ if(current_time > time_last_packet_sent + 500 ){ // change back to 100 payload[3] = PING<<4; rf_transmit_data(); } // if anything gets received, initialize & return if(input(TRW_DR1)){ q_in = 0; q_out = 0; k = 0; unsent_bytes = 0; outgoing_sequence_number = 0; expected_sequence_number = 0; time_last_user_data_sent = 0; time_last_packet_sent = 0; return; } } } // ------------------------ Handle I/O --------------------------- // return only if connection is lost void handle_io(void) { /* payload[0] data 0 payload[1] data 1 payload[2] data 2 payload[3] left nibble: packet type, right nibble: # of bytes payload[4] packet # needing an ack payload[5] packet # getting an ack */ // CLEAR FLAGS WAITING_FOR_ACK = FALSE; WAITING_FOR_PONG = FALSE; NEED_TO_SEND_ACK = FALSE; NEED_TO_RESEND_DATA = FALSE; while(1){ // SOMETHING ARRIVED AT THE RF MODULE? if(input(TRW_DR1)){ receive_and_process(); } // NEED TO SEND AN ACK? if(NEED_TO_SEND_ACK == TRUE){ // send an ack assemble_and_send_packet(); } // MORE THAN 10ms SINCE DATA SENT, BUT STILL NO ACK? if(WAITING_FOR_ACK == TRUE && current_time > time_last_user_data_sent + 10){ // re-send the data NEED_TO_RESEND_DATA = TRUE; assemble_and_send_packet(); } // SOMETHING IN THE UART BUFFER? // if(q_in != q_out && WAITING_FOR_ACK == FALSE AND (current_time > time_last_packet_received+5)){ // <----TEMP // send some data assemble_and_send_packet(); } // NOTHING RECEIVED FOR 200ms? if(current_time> time_last_packet_sent + 200 ){ // send a ping payload[3] = PING * 16; rf_transmit_data(); } // give up on ack? if(WAITING_FOR_ACK == TRUE && current_time> time_waiting_for_ack + 200 ){ // no responce if(DEBUG) putc('A'); return; } // NOTHING RECEIVED FOR 800ms? if(current_time> time_last_packet_received + 800 ){ if(DEBUG) putc('B'); return; } // BUFFER OVERFLOW? if(unsent_bytes>=30){ if(DEBUG) printf("\r\n*unsent bytes %u*", unsent_bytes); } }// end of polling loop } // end of function //---------------------------------------------------------------------- void receive_and_process(void) { getBuf(); // get packet (buf) time_last_packet_received = current_time; // for link timeout number_of_user_bytes_in = payload[3]%16; // the right half of the byte payload_type = payload[3]/16; // the left half of the byte /* if(payload_type <= ACK_AND_DATA) printf( "\r\nIN:%c%c%c, %x, %u(%u), %u(%u)", payload[0],payload[1],payload[2], payload[3],payload[4], expected_sequence_number,payload[5],outgoing_sequence_number); */ // 1) IF PACKET CONTAINS A PROPER ACK if ((payload_type == ACK || payload_type == ACK_AND_DATA) && payload[5] == outgoing_sequence_number && WAITING_FOR_ACK == TRUE){ outgoing_sequence_number++; WAITING_FOR_ACK = FALSE; if (payload_type == ACK) return; } // 2) IF PACKET CONTAINS NEW DATA if((payload_type == USER_DATA || payload_type == ACK_AND_DATA) && payload[4] == expected_sequence_number){ // send to UART bputc(payload[0]); if(number_of_user_bytes_in >= 2) bputc(payload[1]); if(number_of_user_bytes_in >= 3) bputc(payload[2]); expected_sequence_number++; NEED_TO_SEND_ACK = TRUE; return; } // 3) IF PACKET CONTAINS OLD DATA // We got this packet a moment ago. The other unit didn't get get the // ack we sent so it re-sent the packet. We need to re-send the ack, // but first we should add some data from the UART if there's any. // If not we'll send the ack by itself if ((payload_type == USER_DATA || payload_type == ACK_AND_DATA) && payload[4]+1 == expected_sequence_number){ NEED_TO_SEND_ACK = TRUE; WAITING_FOR_ACK = FALSE; return; } // 4) if(payload_type == PING){ payload[3] = PONG<<4; rf_transmit_data(); time_last_packet_received = current_time; return; } // 5) if (payload_type == PONG){ time_last_packet_received = current_time; WAITING_FOR_PONG = FALSE; return; } // IF NOTHING ELSE printf( "\r\n?%c%c%c,%x,%u,%u,%u,%u?", payload[0],payload[1],payload[2], payload[3],payload[4],payload[5], outgoing_sequence_number,expected_sequence_number); } // end of function //-------------------------------------- void rf_transmit_data(void){ trwSetTx(); // switch to transmit // delay_us(1); putBuf(); // send packet (buf) delay_us(448); // transmit time (8+40+48+16)/.250 delay_us(200); // trwSetRx(); // switch back to receive // delay_us(1); time_last_packet_sent = current_time; /*printf( "\r\n|%c%c%c,%x,%u,%u,%u,%u|", payload[0],payload[1],payload[2], payload[3],payload[4],payload[5], outgoing_sequence_number,expected_sequence_number); */ } //--------------------------------------- void putByte( byte b ) { //msb bit first int8 i; for(i=0 ; i < 8 ; i++) { output_low(TRW_CLK1); if(bit_test(b,7)) output_high(TRW_DATA); else output_low(TRW_DATA); // delay_us(10); output_high(TRW_CLK1); // clock out on rising edge // delay_us(10); b=b<<1; } } byte getByte() { //msb bit first int8 i , b = 0; for(i=0 ; i < 8 ; i++) { output_low(TRW_CLK1); CLKDELAY(); output_high(TRW_CLK1); CLKDELAY(); // read before falling edge b<<=1; if( input(TRW_DATA) ) b++; //delay_us(20); } return b; } void trwConfig() { output_low(TRW_CE); output_low(TRW_CS); output_low(TRW_CLK1); output_low(TRW_DATA); PWUPDELAY(); output_high(TRW_CS); CSDELAY(); //msb byte first putByte(DATA2_W); putByte(DATA1_W); putByte(ADDR2_4); putByte(ADDR2_3); putByte(ADDR2_2); putByte(ADDR2_1); putByte(ADDR2_0); putByte(ADDR1_4); putByte(ADDR1_3); putByte(ADDR1_2); putByte(ADDR1_1); putByte(ADDR1_0); putByte(ADDR_W | CRC_L | CRC_EN); putByte(RX2_EN | CM | RFDR_SB | XO_F | RF_PWR); putByte(RF_CH | RXEN); //lsb byte last output_float(TRW_DATA); output_low(TRW_CE); output_low(TRW_CS); output_low(TRW_CLK1); } void trwSetTxByte() { output_low(TRW_CE); output_high(TRW_CS); CSDELAY(); putByte(RF_CH); output_low(TRW_CS); output_low(TRW_CLK1); } void trwSetTx() { output_low(TRW_CE); //output_low(PIN_C0); output_high(TRW_CS); CSDELAY(); output_low(TRW_DATA); output_high(TRW_CLK1); CLKDELAY(); output_low(TRW_CLK1); CLKDELAY(); output_low(TRW_CS); output_low(TRW_CLK1); } void trwSetRxByte() { output_low(TRW_CE); output_high(TRW_CS); CSDELAY(); putByte(RF_CH | RXEN); output_low(TRW_CS); output_float(TRW_DATA); output_low(TRW_CLK1); output_high(TRW_CE); } void trwSetRx() { output_low(TRW_CE); //output_low(PIN_C0); output_high(TRW_CS); CSDELAY(); output_high(TRW_DATA); output_high(TRW_CLK1); CLKDELAY(); output_low(TRW_CLK1); CLKDELAY(); output_low(TRW_CS); output_float(TRW_DATA); output_low(TRW_CLK1); output_high(TRW_CE); //output_high(PIN_C0); } void putBuf() { int8 i; //#define B_TRIS 0b01000111 //#use fast_io(B) output_high(TRW_CE); //output_high(PIN_C0); CSDELAY(); putByte(ADDR1_1); putByte(ADDR1_0); for( i=0; i= BUFFER_SIZE) q_in = 0; unsent_bytes++; //time1 = current_time; } } //--------------------------------------- #int_tbe void serial_isr2() { putc(t_buffer[t_next_out]); t_next_out=(t_next_out+1) % T_BUFFER_SIZE; if(t_next_in==t_next_out) disable_interrupts(int_tbe); } void bputc(char c) { short restart; int ni; restart=t_next_in==t_next_out; t_buffer[t_next_in]=c; ni=(t_next_in+1) % T_BUFFER_SIZE; while(ni==t_next_out); t_next_in=ni; if(restart) enable_interrupts(int_tbe); } //--------------------------------------- #int_timer2 void timer2_isr() { // 4 mhz clock // set timer 2 to overflow in 1ms current_time++; } //---------------------- char get_from_buffer(void){ char t; t = q[q_out]; q_out++; if( q_out >= BUFFER_SIZE) q_out = 0; unsent_bytes--; return t; } //-------------------------- void get_data_from_uart_if_any(void) { number_of_outgoing_user_bytes = 0; if(q_in != q_out) { user[0] = get_from_buffer(); number_of_outgoing_user_bytes++; } if(q_in != q_out) { user[1] = get_from_buffer(); number_of_outgoing_user_bytes++; } if(q_in != q_out) { user[2] = get_from_buffer(); number_of_outgoing_user_bytes++; } } //--------------------------------------------------- void assemble_and_send_packet(void) { // number_of_outgoing_user_bytes = 0; // BUG! payload_type = 6; // to catch errors if(NEED_TO_SEND_ACK == TRUE){ // payload[5] = payload[4]; NEED_TO_SEND_ACK = FALSE; payload_type = ACK; } // if > 10ms since last sending attempt, re-send data if(NEED_TO_RESEND_DATA == TRUE){ payload[0] = user[0]; payload[1] = user[1]; payload[2] = user[2]; // payload[0] = '+'; // payload[1] = '-'; // payload[2] = '='; payload[4] = outgoing_sequence_number; time_last_user_data_sent = current_time; WAITING_FOR_ACK = TRUE; if(payload_type == ACK) payload_type = ACK_AND_DATA; else payload_type = USER_DATA; payload[3] = payload_type * 16 + number_of_outgoing_user_bytes; rf_transmit_data(); NEED_TO_RESEND_DATA = FALSE; /* printf( "\r\n+%c%c%c,%x,%u,%u,%u,%u+", payload[0],payload[1],payload[2], payload[3],payload[4],payload[5], outgoing_sequence_number,expected_sequence_number); */ return; } //if new data to send // (can't send more data until the last data is acknowleged) if(q_in != q_out && WAITING_FOR_ACK == FALSE){ get_data_from_uart_if_any(); payload[0] = user[0]; payload[1] = user[1]; payload[2] = user[2]; payload[4] = outgoing_sequence_number; time_last_user_data_sent = current_time; WAITING_FOR_ACK = TRUE; time_waiting_for_ack = current_time; if(payload_type == ACK) payload_type = ACK_AND_DATA; else payload_type = USER_DATA; payload[3] = payload_type * 16 + number_of_outgoing_user_bytes; rf_transmit_data(); return; } // sending ack without data payload[3] = ACK * 16; rf_transmit_data(); /* printf( "\r\nOUT:%c%c%c, %x, %u(%u), %u(%u)", payload[0], payload[1], payload[2], payload[3], payload[4], outgoing_sequence_number, payload[5], expected_sequence_number); */ }