Test setup: One working golden master device is in viccinity to the test node running this software as it is
Test: Initialize and power Chipcon Read/Write Chipcon Registers: Error if values differ Send Packet to golden master (which blinks all LEDs on packet reception) Receive Packet: Error if no packet received or data not correct
00001 /* 00002 * Copyright (C) 2000-2005 by ETH Zurich 00003 * 00004 * Redistribution and use in source and binary forms, with or without 00005 * modification, are permitted provided that the following conditions 00006 * are met: 00007 * 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the copyright holders nor the names of 00014 * contributors may be used to endorse or promote products derived 00015 * from this software without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY ETH ZURICH AND CONTRIBUTORS 00018 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00019 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00020 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ETH ZURICH 00021 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00022 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00023 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 00024 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 00025 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00026 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 00027 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00028 * SUCH DAMAGE. 00029 * 00030 * For additional information see http://www.btnode.ethz.ch 00031 * 00032 */ 00033 00052 // nut 00053 #include <stdio.h> 00054 #include <dev/usartavr.h> 00055 #include <io.h> 00056 #include <sys/atom.h> 00057 #include <sys/timer.h> 00058 #include <sys/event.h> 00059 #include <dev/irqreg.h> 00060 00061 // btnode3 00062 #include <hardware/btn-hardware.h> 00063 #include <led/btn-led.h> 00064 00065 // chipcon 00066 #include <cc/crc.h> 00067 #include <cc/cc1000.h> 00068 #include <cc/cc1000_defs.h> 00069 //#include <cc/sniffer.h> 00070 00071 // stand alone app uses printf_P, bt-cmd used DEBUGT from Terminal 00072 #ifndef USED_FROM_BTCMD 00073 #define DEBUGT(text, ...) printf_P(PSTR(text),## __VA_ARGS__) 00074 #endif 00075 00076 00077 // #define OLDNODE 00078 // #define ONEWAY 00079 00083 #define PREAMBLE_THRESH 6 //number of preamble bytes receiver needs to listen 00084 #define PREAMBLE_LEN 16 //number of preamble bytes sender needs to send 00085 #define PREAMBLE_BYTE 0xAA // 10101010 00086 #define SYNC_BYTE 0x33 // 00110011 used as start of packet 00087 #define FLUSH_BYTE 0xFF // 11111111 00088 00089 #define STATE_INIT 0 00090 00091 #define STATE_RECV_IDLE 1 00092 #define STATE_RECV_PRE 2 00093 #define STATE_RECV_SYNC 3 00094 #define STATE_RECV_SIZE 4 00095 #define STATE_RECV_DATA 5 00096 #define STATE_RECV_CRC_H 6 00097 #define STATE_RECV_CRC_L 7 00098 00099 #define STATE_SEND_PRE 8 00100 #define STATE_SEND_SYNC 9 00101 #define STATE_SEND_SIZE 10 00102 #define STATE_SEND_DATA 11 00103 #define STATE_SEND_FLUSH 12 00104 #define STATE_SEND_CRC_H 13 00105 #define STATE_SEND_CRC_L 14 00106 #define STATE_SEND_DONE 15 00107 00108 #define STATE_FINISHED 16 00109 00110 #define MAX_DATA_SIZE 32 // maximum data size sender can send 00111 00112 struct Buff{ 00113 u_char size; 00114 u_char data[MAX_DATA_SIZE]; 00115 }; 00116 00117 u_char state = STATE_INIT; 00118 //u_char count=0; 00119 HANDLE bttestRecvHandle=0,bttestSendHandle=0; 00120 u_char bttestprevData=0, spData, bttestpreambleCount=0, bttestoffset=0, bttestdataCount=0, crcHigh,crcLow; 00121 struct Buff RecvBuff,SendBuff; 00122 00123 00124 /* 00125 * Protocol for sending and receiving packet 00126 */ 00127 00128 // spi handler which will be called when a byte is sent or received 00129 void Protocol(void* arg){ 00130 switch(state){ 00131 00132 case STATE_RECV_IDLE: 00133 spData=SPDR; 00134 if(spData == 0xAA || spData == 0x55) //we are in preamble 00135 { 00136 bttestpreambleCount = 0; 00137 state = STATE_RECV_PRE; 00138 } 00139 break; 00140 00141 case STATE_RECV_PRE: 00142 spData=SPDR; 00143 if(spData != 0xAA && spData != 0x55) //not in preamble anymore 00144 { 00145 if(bttestpreambleCount > PREAMBLE_THRESH) //reached end of preamble 00146 { 00147 state = STATE_RECV_SYNC; 00148 bttestoffset = 0; 00149 } 00150 else //just looking at noise 00151 { 00152 state = STATE_RECV_IDLE; 00153 } 00154 } 00155 else //just seeing more of the preamble 00156 { 00157 bttestpreambleCount++; 00158 } 00159 bttestprevData = spData; 00160 break; 00161 00162 case STATE_RECV_SYNC: 00163 spData=SPDR; 00164 /* Figure out the bit offset by shifting until the sync byte. */ 00165 while(bttestprevData != SYNC_BYTE && bttestoffset < 8) 00166 { 00167 bttestprevData = (bttestprevData << 1) | (spData >> (7-bttestoffset)); 00168 bttestoffset++; 00169 } 00170 00171 if(bttestoffset >= 8) //didn't get the sync byte... Something is wrong 00172 { 00173 state = STATE_RECV_IDLE; 00174 } 00175 else 00176 { 00177 /* We are synced and ready to start getting the packet. */ 00178 state = STATE_RECV_SIZE; 00179 bttestprevData = spData; 00180 } 00181 break; 00182 00183 case STATE_RECV_SIZE: 00184 spData = SPDR; 00185 /* Grab the packet size and verify that it isn't larger than 00186 the maximum data size. */ 00187 RecvBuff.size = (bttestprevData << bttestoffset) | (spData >> (8-bttestoffset)); 00188 if(RecvBuff.size > MAX_DATA_SIZE || RecvBuff.size == 0) 00189 { 00190 //something is wrong--packet is zero size, or too large to recv 00191 state = STATE_RECV_IDLE; 00192 } 00193 else 00194 { 00195 //ready to recv data 00196 bttestdataCount = 0; 00197 //RecvBuff.data=(u_char*) malloc(RecvBuff.size*sizeof(u_char)); 00198 state = STATE_RECV_DATA; 00199 } 00200 bttestprevData = spData; 00201 break; 00202 00203 00204 case STATE_RECV_DATA: 00205 spData=SPDR; 00206 RecvBuff.data[bttestdataCount]=(bttestprevData << bttestoffset) | (spData >> (8-bttestoffset)); 00207 bttestdataCount++; 00208 /* Once we have the whole packet, get the crc*/ 00209 if(bttestdataCount == RecvBuff.size) 00210 state = STATE_RECV_CRC_H; 00211 bttestprevData = spData; 00212 break; 00213 00214 case STATE_RECV_CRC_H: 00215 //store high byte of crc 00216 spData = SPDR; 00217 crcHigh = (bttestprevData << bttestoffset) | (spData >> (8-bttestoffset)); 00218 //ready to recv low byte 00219 state = STATE_RECV_CRC_L; 00220 bttestprevData = spData; 00221 break; 00222 00223 case STATE_RECV_CRC_L: 00224 //read low byte and assemble full crc 00225 spData = SPDR; 00226 crcLow = (bttestprevData << bttestoffset) | (spData >> (8-bttestoffset)); 00227 //if crc checks out, swap buffer up to com layer 00228 // if(crc_ccitt_compute(RecvBuff.data, RecvBuff.size) == ((((u_long)crcHigh) << 8) | crcLow)) 00229 if (1) 00230 { 00231 state = STATE_RECV_IDLE; 00232 00233 //disable the spi interrupt 00234 SPCR &= ~(1 << SPIE); 00235 00236 //resume the thread 00237 NutEventPostAsync(&bttestRecvHandle); 00238 } 00239 else 00240 { 00241 state = STATE_RECV_IDLE; 00242 } 00243 break; 00244 00245 00246 00247 case STATE_SEND_PRE: 00248 SPDR = PREAMBLE_BYTE; 00249 bttestpreambleCount++; 00250 if(bttestpreambleCount == PREAMBLE_LEN) 00251 state = STATE_SEND_SYNC; 00252 break; 00253 00254 case STATE_SEND_SYNC: 00255 SPDR = SYNC_BYTE; 00256 state = STATE_SEND_SIZE; 00257 break; 00258 00259 case STATE_SEND_SIZE: 00260 SPDR = SendBuff.size; 00261 bttestdataCount = 0; 00262 state = STATE_SEND_DATA; 00263 break; 00264 00265 case STATE_SEND_DATA: 00266 SPDR = SendBuff.data[bttestdataCount]; 00267 bttestdataCount++; 00268 if(bttestdataCount == SendBuff.size) 00269 state = STATE_SEND_CRC_H; 00270 break; 00271 00272 case STATE_SEND_CRC_H: 00273 SPDR = crcHigh; 00274 state = STATE_SEND_CRC_L; 00275 break; 00276 00277 case STATE_SEND_CRC_L: 00278 SPDR = crcLow; 00279 state = STATE_SEND_FLUSH; 00280 break; 00281 00282 case STATE_SEND_FLUSH: 00283 SPDR = FLUSH_BYTE; 00284 state = STATE_FINISHED; 00285 00286 //disable the spi interrupt 00287 SPCR &= ~(1 << SPIE); 00288 00289 // resume the thread 00290 NutEventPostAsync(&bttestSendHandle); 00291 break; 00292 00293 case STATE_INIT: 00294 default: 00295 break; 00296 } 00297 } 00298 00299 00300 /* 00301 \brief use Protocol SPI handler without interrupts for sending 00302 */ 00303 00304 void ProtocolSend(void){ 00305 while ( state != STATE_FINISHED) { 00306 while ( (SPSR & BV(SPIF)) == 0); 00307 Protocol( (void *) 0); 00308 } 00309 } 00310 00315 u_char cc1000_recv(u_short timeout){ 00316 00317 cc1000_rxmode(); 00318 00319 bttestprevData=0; 00320 bttestpreambleCount=0; 00321 bttestoffset=0; 00322 state=STATE_RECV_IDLE; 00323 00324 //enable the spi interrupt 00325 SPCR |= (1 << SPIE); 00326 00327 if (NutEventWaitNext(&bttestRecvHandle, timeout) == 0) 00328 return 1; 00329 00330 return 0; 00331 } 00332 00338 void cc1000_send(void){ 00339 u_long crc; 00340 00341 NutEnterCritical(); 00342 00343 bttestpreambleCount=0; 00344 if(SendBuff.size==0 || SendBuff.size>MAX_DATA_SIZE) 00345 return; 00346 00347 state=STATE_SEND_PRE; 00348 00349 //compute crc now, so we don't have to do it in interrupt handler 00350 crc = crc_ccitt_compute(SendBuff.data, SendBuff.size); 00351 crcLow = crc & 0x00FF; 00352 crcHigh = (crc & 0xFF00) >> 8; 00353 00354 cc1000_txmode(); 00355 00356 //enable the spi interrupt 00357 // SPCR |= (1 << SPIE); 00358 00359 //suspend and wait while the packet is sent 00360 // NutEventWaitNext(&bttestSendHandle,NUT_WAIT_INFINITE); 00361 00362 ProtocolSend(); 00363 00364 // cc1000_rxmode(); 00365 00366 NutExitCritical(); 00367 00368 } 00369 00370 00371 /* adc initialization*/ 00372 void bttest_cc_rssi_adc_init(void){ 00373 uint8_t temp; 00374 ADCSRA = (1 << ADEN); 00375 ADMUX = 2; //CC1000_RSSI_ADC; //2 for btnode, 0 for mica2 00376 // ADMUX |= BV(ADLAR); //left adjusted, only read ADCH 00377 00378 // first conversion takes 25 adc cycles 00379 ADCSRA |= (1 << ADSC); 00380 while(ADCSRA & (1<<ADSC)); 00381 temp=ADCL; 00382 temp=ADCH; 00383 } 00384 00385 00386 void cc_on(void){ 00387 00388 #ifndef OLDNODE 00389 // turn on chipcon 00390 btn_hardware_config_latch_set(CC1000_POWER_ON_PIN); 00391 #endif 00392 00393 //adc initialization 00394 bttest_cc_rssi_adc_init(); 00395 00396 // wait 10 ms (2 ms crystal startup time) 00397 NutSleep( 10 ); 00398 00399 cc1000_init(0); 00400 00401 //register handler 00402 state = STATE_INIT; 00403 NutRegisterIrqHandler(&sig_SPI,Protocol,0); 00404 } 00405 00406 00407 void cc_tune_868300(void){ 00408 00409 // setup rx and tx channel for 868.3 MHz 00410 cc1000_init(0x1d); 00411 00412 // FRX - CDF02B: 868150000 00413 cc1000_write(1, 0xCD ); 00414 cc1000_write(2, 0xF0 ); 00415 cc1000_write(3, 0x2B ); 00416 00417 // FTX - CDF757: 868268000 00418 cc1000_write(4, 0xCD ); 00419 cc1000_write(5, 0xF7 ); 00420 cc1000_write(6, 0x57 ); 00421 00422 cc1000_calibrate(); 00423 // rx and tx channels are initialized and calibrated 00424 } 00425 00426 00431 u_char cc_test_registers(void) 00432 { 00433 u_char i; 00434 u_char ok = 1; 00435 00436 // DEBUGT( "Testing read/write registers\n\r"); 00437 00438 for (i = 0; i < 255 ; i++) { 00439 cc1000_write(1, i ); 00440 if (cc1000_read( 1 ) != i ) 00441 ok = 0; 00442 } 00443 00444 if (ok == 0) 00445 DEBUGT( "Chipcon Error: Read/Write Registers Failed !!!\n\r"); 00446 return ok; 00447 } 00448 00449 00453 u_char cc_test_packet(void){ 00454 00455 u_char i; 00456 u_short sent = 0, received; 00457 u_short crc_ok = 0; 00458 u_char ok = 1; 00459 u_char errors; 00460 00461 btn_hardware_config_latch_clear(LED0); 00462 btn_hardware_config_latch_clear(LED1); 00463 btn_hardware_config_latch_clear(LED2); 00464 btn_hardware_config_latch_clear(LED3); 00465 00466 received = 0; 00467 00468 // fill buffer 00469 for (i=0; i < MAX_DATA_SIZE; i++) 00470 SendBuff.data[i] = i+i; 00471 SendBuff.size = MAX_DATA_SIZE; 00472 00473 #ifndef ONEWAY 00474 for (sent=0; sent < 100 ; sent++) { 00475 00476 // DEBUGT("sending %d\n", sent); 00477 // send packet 00478 cc1000_send(); 00479 #else 00480 00481 while (1) { 00482 00483 #endif 00484 00485 // clear receive buffer 00486 for (i=0; i < MAX_DATA_SIZE; i++) 00487 RecvBuff.data[i] = 0; 00488 00489 // receive packet in 1000 ms (if packet is returned, CRC is ok!) 00490 if (cc1000_recv(500) != 0) 00491 { 00492 received++; 00493 00494 // check packet 00495 ok = 1; errors = 0; 00496 for (i=0; i < MAX_DATA_SIZE; i++){ 00497 if (RecvBuff.data[i] != SendBuff.data[i]){ 00498 ok = 0; 00499 errors++; 00500 } 00501 } 00502 if (ok) { 00503 DEBUGT("+"); 00504 crc_ok++; 00505 } 00506 else { 00507 DEBUGT("\n\r:"); 00508 for (i=0; i < MAX_DATA_SIZE; i++){ 00509 if (RecvBuff.data[i] == SendBuff.data[i]) 00510 DEBUGT("---- "); 00511 else 00512 DEBUGT("%02x%02x ", SendBuff.data[i], RecvBuff.data[i] ); 00513 } 00514 DEBUGT("\n\r"); 00515 } 00516 } 00517 else 00518 DEBUGT("."); 00519 00520 btn_hardware_config_latch_clear(LED2); 00521 btn_hardware_config_latch_clear(LED3); 00522 00523 NutSleep( 100 ); 00524 00525 btn_hardware_config_latch_set(LED2); 00526 btn_hardware_config_latch_set(LED3); 00527 00528 } 00529 00530 ok = 1; 00531 DEBUGT("Chipcon Test: packets send %d, received %d, crc_ok %d\n\r", sent, received, crc_ok); 00532 if (crc_ok > 95) 00533 DEBUGT("Chipcon Test: O.K. "); 00534 else { 00535 DEBUGT("Chipcon Test: Failed, too many bit errors "); 00536 ok = 0; 00537 } 00538 DEBUGT("\n"); 00539 00540 return ok; 00541 } 00542 00543 00549 void cc_test_echo(char * arg){ 00550 00551 u_char i; 00552 00553 DEBUGT("Chipcon Production Test - Echo Test Mode\n\r"); 00554 btn_hardware_config_latch_clear(LED0); 00555 btn_hardware_config_latch_clear(LED1); 00556 btn_hardware_config_latch_clear(LED2); 00557 btn_hardware_config_latch_clear(LED3); 00558 00559 NutEnterCritical(); 00560 00561 cc_on(); 00562 cc_tune_868300(); 00563 00564 for (i=0; i < MAX_DATA_SIZE; i++) 00565 SendBuff.data[i] = i+i; 00566 SendBuff.size = MAX_DATA_SIZE; 00567 00568 while (1){ 00569 00570 #ifndef ONEWAY 00571 // get packet 00572 cc1000_recv(NUT_WAIT_INFINITE); 00573 #endif 00574 00575 // blink on 00576 #ifdef OLDNODE 00577 PORTC |= BV ( 0 ) | BV ( 1 ); 00578 #else 00579 btn_hardware_config_latch_set(LED0); 00580 btn_hardware_config_latch_set(LED1); 00581 #endif 00582 00583 // send packet 00584 cc1000_send(); 00585 00586 #ifdef ONEWAY 00587 NutSleep ( 300 ); 00588 #endif 00589 00590 #ifndef ONEWAY 00591 00592 // get packet 00593 cc1000_recv(NUT_WAIT_INFINITE); 00594 #endif 00595 00596 // blink off 00597 #ifdef OLDNODE 00598 PORTC &= ~ ( BV ( 0 ) | BV ( 1 ) ); 00599 #else 00600 btn_hardware_config_latch_clear(LED0); 00601 btn_hardware_config_latch_clear(LED1); 00602 #endif 00603 // send packet 00604 cc1000_send(); 00605 00606 #ifdef ONEWAY 00607 NutSleep ( 300 ); 00608 #endif 00609 } 00610 NutExitCritical(); 00611 } 00612 00622 void cc_test(char * arg) { 00623 // on 00624 cc_on(); 00625 00626 // test registers 00627 if (cc_test_registers()){ 00628 00630 cc_tune_868300(); 00631 00632 // test packet sending 00633 // return cc_test_packet(); 00634 cc_test_packet(); 00635 } 00636 // return 0; 00637 } 00638 00639 00640 #ifndef USED_FROM_BTCMD 00641 int main(void){ 00642 u_long baud = 115200; 00643 00644 /* 00645 * Register the UART device, open it, assign stdout to it and set 00646 * the baudrate. 00647 */ 00648 NutRegisterDevice(&devUsartAvr0, 0, 0); 00649 freopen("uart0", "w", stdout); 00650 _ioctl(_fileno(stdout), UART_SETSPEED, &baud); 00651 00652 DEBUGT("\n\rChipcon Production Test Standalone Version\n\r"); 00653 00654 #ifdef OLDNODE 00655 // power on 00656 00657 // if patched, then PORTC is the latch 00658 DDRC = 0xff; 00659 PORTC = BV (CC1000_POWER_ON_PIN) | BV ( 1 ); // CC on, BT off, LEDSs off but 2. 00660 00661 #else 00662 // init config latch 00663 btn_hardware_config_latch_init(); 00664 #endif 00665 00666 // try as node 00667 DEBUGT("TEST APP\n\r"); 00668 cc_test(""); 00669 00670 // act as echo partner 00671 cc_test_echo(""); 00672 DEBUGT("ECHO APP\n\r"); 00673 00674 while (1); 00675 } 00676 #else 00677 00678 #ifdef OLDNODE 00679 #error "OLDNODE not supported for Test App" 00680 #endif 00681 00682 void cc_test_register_cmds(void){ 00683 btn_terminal_register_cmd("cctest", cc_test); 00684 btn_terminal_register_cmd("ccecho", cc_test_echo); 00685 } 00686 00687 #endif