bttest/cc1000-test.c

Date:
08.07.2004
Author:
Jan Beutel <j.beutel@ieee.org>
Production test application using the Chipcon CC1000 module on BTnode Rev3

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

Generated on Tue Jan 23 21:12:24 2007 for BTnut System Software by doxygen 1.4.7