/******************************************************************************************************* * * * ********** * * ************ * * *** *** * * *** +++ *** * * *** + + *** * * *** + CHIPCON CC2420DBK EXAMPLES * * *** + + *** RF Blinking LED Demo - Application Note 033 * * *** +++ *** * * *** *** * * ************ * * ********** * * * ******************************************************************************************************* * This program demonstrates the use of the CC2420DB library, including the basic RF library. The * * packet protocol being used is a small subset of the IEEE 802.15.4 standard. It uses an 802.15.4 MAC * * compatible frame format, but does not implement any other MAC functions/mechanisms (e.g. CSMA-CA). * * The basic RF library can thus not be used to communicate with compliant 802.15.4 networks. * * * * A MSP430F1611 running this program will establish a point-to-point RF link on channel 26 with * * a CC2420DB using the following node addresses: * * - PAN ID: 0x2420 (both nodes) * * - Short address: * * 0x5678 * * Destination address: 0x1234 * * * * This application is intended to work with the blinking LED application on a CC2420DB. * * The pot-meter on the CC2420DB can be used to change the blinking frequency of the diode on * * the MSP-FET430P140 board. * * Please note that there is no so-called (PAN) coordinator. * * * * INSTRUCTIONS: * * Outgoing data packets containing a 10-byte payload will be transmitted each 50th cycle of the * * main program loop. Byte 0 contains the LED dimmer value to the CC2420DBB, byte 1 contains the * * status byte from CC2420 and bytes 2/3 the number of packets received from the CC2420DB. * * This application uses the value of byte 0 FROM the CC2420DB to regulate the blinking frequency of * * the LED on the MSP-FET430P140. * * * This example is based on the blinking LED example for the CC2420DB board. * ******************************************************************************************************* * Compiler: MSP430 IAR C/C++ compiler or msp430-gcc GNU C compiler * * Target platform: MSP-FET430P140 (can easily be ported to other platforms) * ******************************************************************************************************* * Revision history: * * $Log: rf_blink_led.c,v $ * Revision 1.5 2004/07/26 11:18:13 mbr * Changed PANID from 0xDEAD to 0x2420 * * Revision 1.4 2004/04/05 08:25:52 mbr * Comments changed in header * * Revision 1.3 2004/03/30 14:58:27 mbr * Release for web * * * * * * * *******************************************************************************************************/ #include "include.h" #include "hardware.h" #include #include #include "fll.h" #include "swuart.h" //------------------------------------------------------------------------------------------------------- // Defintions used locally in this file. #define PAYLOAD_SIZE 10 #define RF_CHANNEL 26 /** Delay function. */ void delay(unsigned int d) { while(d--) { nop(); nop(); } } void print_init(void) { WDTCTL = WDTCTL_INIT; //Init watchdog timer P1OUT |= P1OUT_INIT; //Init output data of port1 P1SEL |= P1SEL_INIT; //Select port or module -function on port1 P1DIR |= P1DIR_INIT; //Init port direction register of port1 P2OUT |= P2OUT_INIT; //Init output data of port2 P2SEL |= P2SEL_INIT; //Select port or module -function on port2 P2DIR &= P2DIR_INIT; //Init port direction register of port2 delay(65535); //Wait for watch crystal startup delay(65535); fllInit(); //Init FLL to desired frequency using the 32k768 cystal as reference. TACTL = TACTL_AFTER_FLL; //setup timer (still stopped) CCTL0 = CCIE|CAP|CM_2|CCIS_1|SCS; //select P2.2 with UART signal CCTL1 = 0; // CCTL2 = 0; // TACTL |= MC1; //start timer eint(); //enable interrupts }// print_init void servo_init(void) { /* TBCTL bits are as follows: 15 - 10 : unused 9 - 8 : TASSEL 7 - 6 : ID 5 - 4 : MC 3 : Unused. Keep it 0 2 : TBCLR 1 : TBIE 0 : TBIFG */ P2DIR |= 0x08; TBCTL = 0x0102; //Initialize Timer: TASSEL_1|ID_0|TAIE – Using ACLK with 32678Hz BCSCTL1 &= 0xcf; //setup divider for RTC. No divider...=1. TBR = 0x0000; // Timer register is initialized to 0. } // servo_init static BYTE pulsewidth= 0x00; // LED blinking frequency static BYTE pulsewidthcopy= 0x00; // LED blinking frequency static int pulsestatus = 0; static int cnt = 0x64; void ledFlash(BYTE pulsewidth); //------------------------------------------------------------------------------------------------------- // Basic RF transmission and reception structures BASIC_RF_RX_INFO rfRxInfo; BYTE pRxBuffer[BASIC_RF_MAX_PAYLOAD_SIZE]; //------------------------------------------------------------------------------------------------------- //------------------------------------------------------------------------------------------------------- // BASIC_RF_RX_INFO* basicRfReceivePacket(BASIC_RF_RX_INFO *pRRI) // // DESCRIPTION: // This function is a part of the basic RF library, but must be declared by the application. Once // the application has turned on the receiver, using basicRfReceiveOn(), all incoming packets will // be received by the FIFOP interrupt service routine. When finished, the ISR will call the // basicRfReceivePacket() function. Please note that this function must return quickly, since the // next received packet will overwrite the active BASIC_RF_RX_INFO structure (pointed to by pRRI). // // ARGUMENTS: // BASIC_RF_RX_INFO *pRRI // The reception structure, which contains all relevant info about the received packet. // // RETURN VALUE: // BASIC_RF_RX_INFO* // The pointer to the next BASIC_RF_RX_INFO structure to be used by the FIFOP ISR. If there is // only one buffer, then return pRRI. //------------------------------------------------------------------------------------------------------- BASIC_RF_RX_INFO* basicRfReceivePacket(BASIC_RF_RX_INFO *pRRI) { pulsewidth= pRxBuffer[0]; pulsewidthcopy= pRxBuffer[0]; // Continue using the (one and only) reception structure return pRRI; } // basicRfReceivePacket //------------------------------------------------------------------------------------------------------- // int main (void) // // DESCRIPTION: // Startup routine and main loop //------------------------------------------------------------------------------------------------------- int main (void) { UINT32 j, k; // Initalize ports for communication with CC2420 and other peripheral units PORT_INIT(); // initialize print/usart print_init(); // The main loop: while (TRUE) { for (j = 0; j<200000; j++) k++; TOGGLE_YLED(); printf("Led toggles \r\n"); } } // main //------------------------------------------------------------------------------------------------------- // void ledFlash(BYTE pulsewidth) // // DESCRIPTION: // Toggles the led 'cycles' times with a half-cycle duration of 'period' uSeconds. // // ARGUMENTS: // UINT16 cycles // Number of times to toggle the LED // UINT16 period // Half-cycle period, i.e the time the LED is on respectively off. // //------------------------------------------------------------------------------------------------------- void ledFlash(BYTE pulsewidth) { switch (pulsewidth){ case '1': // CCR0 is what TAR will count upto. 32678/8/8/2– 8 for ID3, 8 for BCSCTL1, 2 as it will toggle after half a second. Count upto 256 (0x0100) // printf("Inside case 1\r\n"); TBCCR0 = 0x0010; CLR_YLED(); P2OUT |= 0x08; pulsestatus=1; TBCTL |= 0x0010; // start Timer in up mode (MC = 1) eint(); // Enable interrupt by setting GIE bit LPM0; break; case '2': // CCR0 is what TAR will count upto. 32678/8/16/2 – 8 for ID3, 16 for BCSCTL1, 2 as it will toggle after half a second. Count upto 256 (0x0100) // printf("Inside case 2\r\n"); TBCCR0 = 0x0018; CLR_YLED(); P2OUT |= 0x08; pulsestatus=1; TBCTL |= 0x0010; // start Timer in up mode (MC = 1) eint(); // Enable interrupt by setting GIE bit LPM0; break; case '3': // CCR0 is what TAR will count upto. 32678/8/16/2 – 8 for ID3, 16 for BCSCTL1, 2 as it will toggle after half a second. Count upto 256 (0x0100) // printf("Inside case 3\r\n"); TBCCR0 = 0x0020; CLR_YLED(); P2OUT |= 0x08; pulsestatus=1; TBCTL |= 0x0010; // start Timer in up mode (MC = 1) eint(); // Enable interrupt by setting GIE bit LPM0; break; case '4': // CCR0 is what TAR will count upto. 32678/8/8/2– 8 for ID3, 8 for BCSCTL1, 2 as it will toggle after half a second. Count upto 256 (0x0100) // printf("Inside case 4\r\n"); TBCCR0 = 0x0028; CLR_YLED(); P2OUT |= 0x08; pulsestatus=1; TBCTL |= 0x0010; // start Timer in up mode (MC = 1) eint(); // Enable interrupt by setting GIE bit LPM0; break; case '5': // CCR0 is what TAR will count upto. 32678/8/8/2– 8 for ID3, 8 for BCSCTL1, 2 as it will toggle after half a second. Count upto 256 (0x0100) // printf("Inside case 5\r\n"); TBCCR0 = 0x0030; CLR_YLED(); P2OUT |= 0x08; pulsestatus=1; TBCTL |= 0x0010; // start Timer in up mode (MC = 1) eint(); // Enable interrupt by setting GIE bit LPM0; break; case '6': // CCR0 is what TAR will count upto. 32678/8/8/2– 8 for ID3, 8 for BCSCTL1, 2 as it will toggle after half a second. Count upto 256 (0x0100) // printf("Inside case 6\r\n"); TBCCR0 = 0x0038; CLR_YLED(); P2OUT |= 0x08; pulsestatus=1; TBCTL |= 0x0010; // start Timer in up mode (MC = 1) eint(); // Enable interrupt by setting GIE bit LPM0; break; case '7': // CCR0 is what TAR will count upto. 32678/8/8/2– 8 for ID3, 8 for BCSCTL1, 2 as it will toggle after half a second. Count upto 256 (0x0100) // printf("Inside case 7\r\n"); TBCCR0 = 0x0040; CLR_YLED(); P2OUT |= 0x08; pulsestatus=1; TBCTL |= 0x0010; // start Timer in up mode (MC = 1) eint(); // Enable interrupt by setting GIE bit LPM0; break; case '8': // CCR0 is what TAR will count upto. 32678/8/8/2– 8 for ID3, 8 for BCSCTL1, 2 as it will toggle after half a second. Count upto 256 (0x0100) // printf("Inside case 8\r\n"); TBCCR0 = 0x0048; CLR_YLED(); P2OUT |= 0x08; pulsestatus=1; TBCTL |= 0x0010; // start Timer in up mode (MC = 1) eint(); // Enable interrupt by setting GIE bit LPM0; break; case '9': // CCR0 is what TAR will count upto. 32678/8/8/2– 8 for ID3, 8 for BCSCTL1, 2 as it will toggle after half a second. Count upto 256 (0x0100) // printf("Inside case 9\r\n"); TBCCR0 = 0x0050; CLR_YLED(); P2OUT |= 0x08; pulsestatus=1; TBCTL |= 0x0010; // start Timer in up mode (MC = 1) eint(); // Enable interrupt by setting GIE bit LPM0; break; } // switch } // ledflash //------------------------------------------------------------------------------------------------------- // SIGNAL(SIG_INTERRUPT0) - CC2420 FIFOP interrupt service routine // // DESCRIPTION: // When a packet has been completely received, this ISR will extract the data from the RX FIFO, put // it into the active BASIC_RF_RX_INFO structure, and call basicRfReceivePacket() (defined by the // application). FIFO overflow and illegally formatted packets are handled by this routine. // // Note: Packets are acknowledged automatically by CC2420 through the auto-acknowledgment feature. //------------------------------------------------------------------------------------------------------- interrupt (PORT1_VECTOR) fifo_rx(void){ UINT8 spiCnt; // UINT8 i; WORD frameControlField; INT8 length; BYTE pFooter[2]; printf("Clearing FIFOP Interrupt....\r\n"); CLEAR_FIFOP_INT(); // Clean up and exit in case of FIFO overflow, which is indicated by FIFOP = 1 and FIFO = 0 if((FIFOP_IS_1) && (!(FIFO_IS_1))) { printf("Detected FIFO Overflow....\r\n"); FASTSPI_STROBE(CC2420_SFLUSHRX); FASTSPI_STROBE(CC2420_SFLUSHRX); return; } // Payload length FASTSPI_READ_FIFO_BYTE(length); // 100 length &= BASIC_RF_LENGTH_MASK; // Ignore MSB printf("Length: %x\r\n", length); // Ignore the packet if the length is too short if (length < BASIC_RF_ACK_PACKET_SIZE) { printf("Detected length < BASIC_RF_ACK_PACKET_SIZE\r\n"); FASTSPI_READ_FIFO_GARBAGE(length); // Otherwise, if the length is valid, then proceed with the rest of the packet } else { // Register the payload length rfSettings.pRxInfo->length = length - BASIC_RF_PACKET_OVERHEAD_SIZE; printf("Length(payload): %x\r\n",rfSettings.pRxInfo->length); // Read the frame control field and the data sequence number FASTSPI_READ_FIFO_NO_WAIT((BYTE*) &frameControlField, 2); rfSettings.pRxInfo->ackRequest = !!(frameControlField & BASIC_RF_FCF_ACK_BM); printf("AckRequest: %x\r\n", rfSettings.pRxInfo->ackRequest); FASTSPI_READ_FIFO_BYTE(rfSettings.pRxInfo->seqNumber); // Is this an acknowledgment packet? if ((length == BASIC_RF_ACK_PACKET_SIZE) && (frameControlField == BASIC_RF_ACK_FCF) && (rfSettings.pRxInfo->seqNumber == rfSettings.txSeqNumber)) { // Read the footer and check for CRC OK FASTSPI_READ_FIFO_NO_WAIT((BYTE*) pFooter, 2); // Indicate the successful ack reception (this flag is polled by the transmission routine) if (pFooter[1] & BASIC_RF_CRC_OK_BM) rfSettings.ackReceived = TRUE; // Too small to be a valid packet? } else if (length < BASIC_RF_PACKET_OVERHEAD_SIZE) { FASTSPI_READ_FIFO_GARBAGE(length - 3); return; // Receive the rest of the packet } else { // Skip the destination PAN and address (that's taken care of by harware address recognition!) FASTSPI_READ_FIFO_GARBAGE(4); // Read the source address FASTSPI_READ_FIFO_NO_WAIT((BYTE*) &rfSettings.pRxInfo->srcAddr, 2); printf("SrcAdd: %x\r\n", rfSettings.pRxInfo->srcAddr); // Read the packet payload FASTSPI_READ_FIFO_NO_WAIT(rfSettings.pRxInfo->pPayload, rfSettings.pRxInfo->length); printf("Payload[0]: %x\r\n", rfSettings.pRxInfo->pPayload[0]); printf("Payload[1]: %x\r\n", rfSettings.pRxInfo->pPayload[1]); // Read the footer to get the RSSI value FASTSPI_READ_FIFO_NO_WAIT((BYTE*) pFooter, 2); printf("pFooter:%x\r\n", pFooter); rfSettings.pRxInfo->rssi = pFooter[0]; // Notify the application about the received _data_ packet if the CRC is OK if (((frameControlField & (BASIC_RF_FCF_BM)) == BASIC_RF_FCF_NOACK) && (pFooter[1] & BASIC_RF_CRC_OK_BM)) { printf("Notifying the application\r\n"); rfSettings.pRxInfo = basicRfReceivePacket(rfSettings.pRxInfo); } } } } // SIGNAL(SIG_INTERRUPT0) interrupt (TIMERB1_VECTOR) IntServiceRoutine(void) { // As this Vector handles four interrupt conditions if(TBCTL & 0x0001){ TBCTL &= 0xfffe; // Clear the interrupt flag if (pulsestatus == 1){ P2OUT &= 0xf7; // P2.3 is low now pulsestatus = 0; cnt--; TBCCR0 = 0x0289 - TBCCR0; pulsewidth = 0; } else{ pulsewidth = pulsewidthcopy; } if (cnt == 0){ TBCTL &= 0xffcf; // stop the timer cnt=0x64; pulsewidth = 0; } TBR = 0x0000; // Timer register is initialized to 0 i.e. Counter is restarted _BIC_SR_IRQ(LPM0_bits); // Low power mode is cleared }//if(TBCTL & 0x0001) }//interrupt