//-------------------------------------------- // Read the SHT M200 sensor module data byte //-------------------------------------------- uint8 SHT_ReadByte(uint8 ack) { uint8 res = 0; uint8 cnt; HAL_I2C_SDA_SET(); HAL_I2C_SDA_DIR_IN(); HAL_I2C_SCL_CLR(); for (cnt = 0; cnt < 8; cnt++) { HAL_I2C_SCL_SET(); halMcuWaitUs(5); res <<= 1; if (HAL_I2C_SDA_VAL()) { res |= 0x01; } HAL_I2C_SCL_CLR(); halMcuWaitUs(5); } HAL_I2C_SDA_DIR_OUT(); halMcuWaitUs(5); if (ack == 1) { HAL_I2C_SDA_CLR(); } HAL_I2C_SCL_SET(); halMcuWaitUs(20); HAL_I2C_SCL_CLR(); HAL_I2C_SDA_SET(); return res; }
/*********************************************************************************** * @fn halRfInit * * @brief Power up, sets default tuning settings, enables autoack and configures * chip IO * * @param none * * @return HAL_RF_SUCCESS if the radio has started, FAILURE otherwise */ uint8 halRfInit(void) { regVal_t* p; DEBUG_MSG_FUNC_START; // Avoid GPIO0 interrupts during reset #if 0 // POOH halDigioIntDisable(&pinRadio_GPIO0); #else CC2520_GPIO_0_Interrupt_Setting(DISABLE); #endif // Make sure to pull the CC2520 RESETn and VREG_EN pins low CC2520_RESET_OPIN(0); CC2520_SPI_END(); CC2520_VREG_EN_OPIN(0); #if 0 // POOH halMcuWaitUs(1100); #else Delay(110); #endif // Make sure MISO is configured as output. #if 0 // POOH CC2520_MISO_DIR_OUT(); #endif // Enable the voltage regulator and wait for it (CC2520 power-up) CC2520_VREG_EN_OPIN(1); #if 0 // POOH halMcuWaitUs(CC2520_VREG_MAX_STARTUP_TIME); #else Delay(200); #endif // Release reset CC2520_RESET_OPIN(1); #if 0 // POOH // Wait for XOSC stable to be announced on the MISO pin if (halRfWaitRadioReady()==HAL_RF_FAILED) return HAL_RF_FAILED; #else Delay(200); #endif // Write non-default register values p= regval; while (p->reg!=0) { CC2520_MEMWR8(p->reg,p->val); p++; } return HAL_RF_SUCCESS; }
/*********************************************************************************** * @fn halSampleED * * @brief Sample Energy Detect * * @param uint8 channel - channel between 11 and 26 * uint16 sampleTime - sample time in us * * @return int8 - sampled RSSI value */ int8 halSampleED(uint8 channel, uint16 sampleTime) { int8 rssi=0; // Set channel halRfSetChannel(channel); // Set RX on halRfReceiveOn(); while (!RSSISTAT); // Enable energy scan mode, using peak signal strength FRMCTRL0 |= 0x10; // Spend sampleTime us accumulating the peak RSSI value halMcuWaitUs(sampleTime); rssi = RSSI; // Exit the current channel halRfReceiveOff(); // Disable ED scan mode FRMCTRL0 &= ~0x10; return rssi; }
/*********************************************************************************** * @fn appRfReceiverTask * * @brief Check if a new packet has been received. If a new packet * is received the payload is sent to the UART. * * @param none * * @return none */ static void appRfReceiverTask(void) { if (mrfiLinkDataRdy()) { uint8 nToSend; uint8 fSuccess; // Tell the PC not to send data halUartEnableRxFlow(FALSE); // Wait for the PC to respond halMcuWaitUs(1000); // Receive RF data nToSend = mrfiLinkRecv(pRxData); // If reception successful, send packet to UART fSuccess= FALSE; if(nToSend>0) { if (halUartWrite(pRxData,nToSend)==nToSend) fSuccess= TRUE; } if (!fSuccess) { nRxErr++; appUpdateDisplay(); } // Signal RX flow on, the PC may send data again halUartEnableRxFlow(TRUE); } }
inline void cpu_delay(uint16 msec) { while(msec-- > 0) { halMcuWaitUs(1000); } }
/* * @fn clockSetMainSrc * * @brief Function for setting the main system clock source. * The function turns off the clock source that is not being used. * TICKSPD is set to the same frequency as the source. * * @param uint8 source (one of CLOCK_SRC_HFRC or CLOCK_SRC_XOSC) * * @return void * */ void clockSetMainSrc(uint8 source) { register uint8 osc32k_bm = CLKCON & CLKCON_OSC32K_BM; // Source can have the following values: // CLOCK_SRC_XOSC 0x00 High speed Crystal Oscillator (XOSC) // CLOCK_SRC_HFRC 0x01 Low power RC Oscillator (HFRC) if (source == CLOCK_SRC_HFRC) { SLEEP &= ~SLEEP_OSC_PD_BM; // power up both oscillators while (!CC2430_IS_HFRC_STABLE());// wait until the oscillator is stable asm("NOP"); CLKCON = (osc32k_bm | CLKCON_OSC_BM | TICKSPD_DIV_1 | CLKCON_CLKSPD_BM); while (CLKCON != (osc32k_bm | CLKCON_OSC_BM | TICKSPD_DIV_1 | CLKCON_CLKSPD_BM)); SLEEP |= SLEEP_OSC_PD_BM; // power down the unused oscillator } else if (source == CLOCK_SRC_XOSC) { SLEEP &= ~SLEEP_OSC_PD_BM; // power up both oscillators while (!CC2430_IS_XOSC_STABLE());// wait until the XOSC is stable asm("NOP"); halMcuWaitUs(64); CLKCON = (osc32k_bm | TICKSPD_DIV_1); while (CLKCON != (osc32k_bm | TICKSPD_DIV_1)); SLEEP |= SLEEP_OSC_PD_BM; // power down the unused oscillator } }
/****************************************************************************** * @fn mrfiLinkSend * * @brief Send data on the RX link. * * @param pBuf - buffer to be transmitted * * @param len - number of bytes to be transmitted * * @return Return code indicates success or failure of transmit: * MRFI_TX_RESULT_SUCCESS - transmit succeeded * MRFI_TX_RESULT_FAILED - transmit failed because CCA or ACK failed */ uint8 mrfiLinkSend(uint8 *pBuf, uint8 len, uint8 nRetrans) { uint8 v,i,status; v= halIntLock(); MRFI_SET_PAYLOAD_LEN(&pkt, len+2); memcpy(MRFI_P_DST_ADDR(&pkt), dest_addr, 4); memcpy(MRFI_P_SRC_ADDR(&pkt), src_addr, 4); MRFI_P_PAYLOAD(&pkt)[0]= seqSend; MRFI_P_PAYLOAD(&pkt)[1]= MRFI_LINK_DATA; memcpy(MRFI_P_PAYLOAD(&pkt)+2, pBuf, len); halIntUnlock(v); for (i=0;i<nRetrans;i++) { status= MRFI_Transmit(&pkt, MRFI_TX_TYPE_CCA); if (status==MRFI_TX_RESULT_SUCCESS) { if (waitForAck(20)) { seqSend++; break; } else { status= MRFI_TX_RESULT_FAILED; // wait random time if sending is not successful // (20-40 milliseconds) halMcuWaitUs( (20000/255*MRFI_RandomByte()) + 20000 ); } } } return status; }
//-------------------------------------------- // Reset the SHT M200 sensor moudule connect //-------------------------------------------- void SHT_ConnectReset(void) { uint8 i; HAL_I2C_SDA_SET(); HAL_I2C_SCL_CLR(); halMcuWaitUs(20); for (i = 0; i < 9; i++) { HAL_I2C_SCL_SET(); halMcuWaitUs(5); HAL_I2C_SCL_CLR(); halMcuWaitUs(5); } halMcuWaitMs(100); }
void small_delay(int x) { int i = 0; for(i=0; i<64; i++) { halMcuWaitUs(x); } }
//------------------------------------------------------------------- // @fn halBuzzer // @brief Turn Buzzer on. // @param uint16 freq //------------------------------------------------------------------- void halBuzzerOn(uint16 ms) { int i; for(i=0; i<ms; i++) { HAL_BUZZER_TGL(); halMcuWaitUs(200); } HAL_BUZZER_OFF(); }
/*********************************************************************************** * @fn halRfInit * * @brief Power up, sets default tuning settings, enables autoack and configures * chip IO * * @param none * * @return SUCCESS if the radio has started, FAILURE otherwise */ uint8 halRfInit(void) { regVal_t* p; uint8 val; // Avoid GPIO0 interrupts during reset // halDigioIntDisable(&pinRadio_GPIO0); // Make sure to pull the CC2520 RESETn and VREG_EN pins low CC2520_RESET_OPIN(0); CC2520_SPI_END(); CC2520_VREG_EN_OPIN(0); halMcuWaitUs(1100); // Make sure MISO is configured as output. // CC2520_MISO_DIR_OUT(); // Enable the voltage regulator and wait for it (CC2520 power-up) CC2520_VREG_EN_OPIN(1); halMcuWaitUs(CC2520_VREG_MAX_STARTUP_TIME); // Release reset CC2520_RESET_OPIN(1); // Wait for XOSC stable to be announced on the MISO pin if (halRfWaitRadioReady()==FAILED) return FAILED; // Write non-default register values p = regval; while (p->reg!=0) { CC2520_MEMWR8(p->reg,p->val); p++; } // Verify a register val= CC2520_MEMRD8(CC2520_MDMCTRL0); return val==0x85? SUCCESS : FAILED; }
/*********************************************************************************** * @fn halRfWaitRadioReady * * @brief Wait for the crystal oscillator to stabilise. * * @param none * * @return HAL_RF_SUCCESS if oscillator starts, HAL_RF_FAILED otherwise */ static uint8 halRfWaitRadioReady(void) { uint8 i; // Wait for XOSC stable to be announced on the MISO pin i= 100; CC2520_CSN_OPIN(0); while (i>0 && !CC2520_MISO_IPIN) { halMcuWaitUs(10); --i; } CC2520_CSN_OPIN(1); return i>0 ? HAL_RF_SUCCESS : HAL_RF_FAILED; }
//-------------------------------------------- // Write the SHT M200 sensor module data byte //-------------------------------------------- uint8 SHT_WriteByte(uint8 dat) { uint8 i, err = 0; for (i = 0; i <8; i++) { if (dat &0x80) { HAL_I2C_SDA_SET(); } else { HAL_I2C_SDA_CLR(); } dat = dat << 1; HAL_I2C_SCL_SET(); halMcuWaitUs(20); HAL_I2C_SCL_CLR(); halMcuWaitUs(20); } HAL_I2C_SDA_SET(); HAL_I2C_SDA_DIR_IN(); HAL_SPI_CS_OUTPUT(); HAL_I2C_SCL_SET(); halMcuWaitUs(5); if (HAL_I2C_SDA_VAL()) { err = 1; } HAL_SPI_CS_DIS(); HAL_I2C_SCL_CLR(); HAL_I2C_SDA_DIR_OUT(); HAL_I2C_SDA_SET(); return err; }
/*********************************************************************************** * @fn halRfTransmit * * @brief Transmit frame with Clear Channel Assessment. * * @param none * * @return uint8 - HAL_RF_SUCCESS or HAL_RF_FAILED */ uint8 halRfTransmit(void) { uint16 timeout = 2500; // 2500 x 20us = 50ms uint8 status=0; // DEBUG_MSG_FUNC_START; // Wait for RSSI to become valid while(!CC2520_RSSI_VALID_PIN); // Reuse GPIO2 for TX_FRM_DONE exception HAL_INT_OFF(); CC2520_CFG_GPIO_OUT(2, 1 + CC2520_EXC_TX_FRM_DONE); HAL_INT_ON(); // Wait for the transmission to begin before exiting (makes sure that this function cannot be called // a second time, and thereby cancelling the first transmission. while(--timeout > 0) { HAL_INT_OFF(); CC2520_INS_STROBE(CC2520_INS_STXONCCA); HAL_INT_ON(); if (CC2520_SAMPLED_CCA_PIN) break; #if 0 // POOH halMcuWaitUs(20); #else Delay(20); #endif } if (timeout == 0) { DEBUG_MSG_FUNC_ERROR; status = HAL_RF_FAILED; CC2520_INS_STROBE(CC2520_INS_SFLUSHTX); } else { status = HAL_RF_SUCCESS; // Wait for TX_FRM_DONE exception while(!CC2520_TX_FRM_DONE_PIN); HAL_INT_OFF(); CC2520_CLEAR_EXC(CC2520_EXC_TX_FRM_DONE); HAL_INT_ON(); } // Reconfigure GPIO2 HAL_INT_OFF(); CC2520_CFG_GPIO_OUT(2, CC2520_GPIO_RSSI_VALID); HAL_INT_ON(); return status; }
/*********************************************************************************** * @fn halRfWaitRadioReady * * @brief Wait for the crystal oscillator to stabilise. * * @param none * * @return SUCCESS if oscillator starts, FAILED otherwise */ static uint8 halRfWaitRadioReady(void) { uint8 i; // Wait for XOSC stable to be announced on the MISO pin i= 100; HAL_MAC_SPI_LUMINARY_SO_AS_GPIO(); CC2520_CSN_OPIN(0); while (i>0 && !CC2520_MISO_IPIN) { halMcuWaitUs(10); --i; } CC2520_CSN_OPIN(1); BSP_SSI0_Init(); return i>0 ? SUCCESS : FAILED; }
/*********************************************************************************** * @fn halRfInit * * @brief Power up, sets default tuning settings, enables autoack, enables random * generator. * * @param none * * @return SUCCESS always (for interface compatibility) */ uint8 halRfInit(void) { uint8 i; // turning on power to analog part of radio and waiting for voltage regulator. RFPWR = 0x04; while( RFPWR & 0x10 ); // Setting for AUTO CRC and AUTOACK MDMCTRL0L |= (AUTO_CRC | AUTO_ACK); // Turning on AUTO_TX2RX FSMTC1 = ((FSMTC1 & (~AUTO_TX2RX_OFF & ~RX2RX_TIME_OFF)) | ACCEPT_ACKPKT); // Turning off abortRxOnSrxon. FSMTC1 &= ~0x20; // Set FIFOP threshold to maximum IOCFG0 = 0x7F; // tuning adjustments for optimal radio performance; details available in datasheet */ RXCTRL0H = 0x32; RXCTRL0L = 0xF5; // Turning on receiver to get output from IF-ADC ISRXON(); halMcuWaitUs(1); // Enable random generator ADCCON1 &= ~0x0C; for(i = 0 ; i < 32 ; i++) { RNDH = ADCTSTH; // Clock random generator ADCCON1 |= 0x04; } ISRFOFF(); // Enable CC2591 with High Gain Mode halPaLnaInit(); halRfEnableRxInterrupt(); return SUCCESS; }
//-------------------------------------------- // Start the SHT M200 sensor module //-------------------------------------------- void SHT_Start(void) { HAL_I2C_SCL_CLR(); HAL_I2C_SDA_SET(); halMcuWaitUs(5); HAL_I2C_SCL_SET(); halMcuWaitUs(5); HAL_I2C_SDA_CLR(); halMcuWaitUs(5); HAL_I2C_SCL_CLR(); halMcuWaitUs(20); HAL_I2C_SCL_SET(); halMcuWaitUs(5); HAL_I2C_SDA_SET(); halMcuWaitUs(5); HAL_I2C_SCL_CLR(); halMcuWaitUs(5); }
/************************************************************************************ * @fn halJoystickPushed * * @brief * This function detects if the joystick is being pushed. The function * implements software debounce. Return true only if previuosly called * with joystick not pushed. Return true only once each time the joystick * is pressed. * * Parameters: * * @param void * * @return uint8 * 1: Button is being pushed * 0: Button is not being pushed * ******************************************************************************/ uint8 halJoystickPushed(void) { uint8 value, active; uint8 i; static uint8 prevValue = 0; uint16 adcValue; // Criterion for button pushed: // 3 times joystick active and in center position value = 1; for (i=0; i<3; i++) { active = MCU_IO_GET(HAL_BOARD_IO_JOY_MOVE_PORT, HAL_BOARD_IO_JOY_MOVE_PIN); adcValue = adcSampleSingle(ADC_REF_AVDD, ADC_9_BIT, \ HAL_BOARD_IO_JOYSTICK_ADC_CH); // Only use 7 out of the 9 bits adcValue = (adcValue & 0x7FC0) >> 8; if (! active || adcValue < 0x54) { // Joystick not active or not in center position value = 0; break; } halMcuWaitUs(3); } if (value){ if (!prevValue){ value = prevValue = 1; halMcuWaitMs(100); } else { value = 0; } } else{ prevValue = 0; } return value; }
/*********************************************************************************** * @fn halSampleED * * @brief Sample Energy Detect * * @param uint8 channel - channel between 11 and 26 * uint16 sampleTime - sample time in us * * @return int8 - sampled RSSI value */ int8 halSampleED(uint8 channel, uint16 sampleTime) { int8 rssi=0; CC2520_REGWR8(CC2520_FREQCTRL, 0x0B + ( (channel-11) * 5)); CC2520_SRXON(); while (!CC2520_REGRD8(CC2520_RSSISTAT)); // Enable ED scan mode CC2520_BSET(CC2520_MAKE_BIT_ADDR(CC2520_FRMCTRL0, 4)); // Spend sampleTime us accumulating the peak RSSI value halMcuWaitUs(sampleTime); rssi = CC2520_REGRD8(CC2520_RSSI); // Exit the current channel CC2520_SRFOFF(); // Disable ED scan mode CC2520_BCLR(CC2520_MAKE_BIT_ADDR(CC2520_FRMCTRL0, 4)); return rssi; }
/*********************************************************************************** * @fn appRfSenderTask * * @brief Checks if new bytes have arrived from the UART. If there * are enough bytes to fill a maximal sized packet, or if the UART * is idle, the bytes are transmitted on the air. * * @param none * * @return none */ static void appRfSenderTask(void) { uint8 nBytes; uint8 payloadLength; uint8 bytesToRead; nBytes = halUartGetNumRxBytes(); payloadLength= 0; bytesToRead= 0; if(nBytes >= APP_PAYLOAD_LENGTH || (appUartRxIdle && nBytes>0) ) { // Signal PC not to send on UART, while sending on air. halUartEnableRxFlow(FALSE); // Wait for PC to respond halMcuWaitUs(1000); bytesToRead = MIN(nBytes, APP_PAYLOAD_LENGTH); halUartRead(pTxData,bytesToRead); payloadLength+= bytesToRead; halLedToggle(3); if( (mrfiLinkSend(pTxData, payloadLength,N_RETRIES)) != MRFI_TX_RESULT_SUCCESS) { nTxErr++; appUpdateDisplay(); } // Signal RX flow on halUartEnableRxFlow(TRUE); // Restart idle timer halTimer32kRestart(); halTimer32kIntEnable(); // Reset idle fimer flag appUartRxIdle = FALSE; } }
/*********************************************************************************** * @fn basicRfSendPacket * * @brief Send packet * * @param destAddr - destination short address * pPayload - pointer to payload buffer. This buffer must be * allocated by higher layer. * length - length of payload * txState - file scope variable that keeps tx state info * mpdu - file scope variable. Buffer for the frame to send * * @return basicRFStatus_t - SUCCESS or FAILED */ uint8 basicRfSendPacket(uint16 destAddr, uint8* pPayload, uint8 length) { uint8 mpduLength; uint8 status; // Turn on receiver if its not on if(!txState.receiveOn) { halRfReceiveOn(); } // Check packet length length = min(length, BASIC_RF_MAX_PAYLOAD_SIZE); // Wait until the transceiver is idle halRfWaitTransceiverReady(); // Turn off RX frame done interrupt to avoid interference on the SPI interface halRfDisableRxInterrupt(); mpduLength = basicRfBuildMpdu(destAddr, pPayload, length); #ifdef SECURITY_CCM halRfWriteTxBufSecure(txMpdu, mpduLength, length, BASIC_RF_LEN_AUTH, BASIC_RF_SECURITY_M); txState.frameCounter++; // Increment frame counter field #else halRfWriteTxBuf(txMpdu, mpduLength); #endif // Turn on RX frame done interrupt for ACK reception halRfEnableRxInterrupt(); // Send frame with CCA. return FAILED if not successful if(halRfTransmit() != SUCCESS) { status = FAILED; } // Wait for the acknowledge to be received, if any if (pConfig->ackRequest) { txState.ackReceived = FALSE; // We'll enter RX automatically, so just wait until we can be sure that the ack reception should have finished // The timeout consists of a 12-symbol turnaround time, the ack packet duration, and a small margin halMcuWaitUs((12 * BASIC_RF_SYMBOL_DURATION) + (BASIC_RF_ACK_DURATION) + (2 * BASIC_RF_SYMBOL_DURATION) + 10); // If an acknowledgment has been received (by RxFrmDoneIsr), the ackReceived flag should be set status = txState.ackReceived ? SUCCESS : FAILED; } else { status = SUCCESS; } // Turn off the receiver if it should not continue to be enabled if (!txState.receiveOn) { halRfReceiveOff(); } if(status == SUCCESS) { txState.txSeqNumber++; } #ifdef SECURITY_CCM halRfIncNonceTx(); // Increment nonce value #endif return status; }
static void halAesOperation(uint8 oper,uint8 *pDataIn, uint16 length, uint8 *pDataOut, uint8 *pInitVector) { uint16 i; uint8 j, k; uint8 mode; uint16 nbrOfBlocks; uint16 convertedBlock; nbrOfBlocks = length / 0x10; if((length % 0x10) != 0){ // length not multiplum of 16, convert one block extra with zeropadding nbrOfBlocks++; } // Loading the IV. halAesLoadBlock(pInitVector, AES_LOAD_IV); // Start the operation AES_SET_OPERATION(oper); // Getting the operation mode. mode = ENCCS & 0x70; for(convertedBlock = 0; convertedBlock < nbrOfBlocks; convertedBlock++){ // Starting the conversion. AES_START(); i = convertedBlock * 16; // Counter, Output Feedback and Cipher Feedback operates on 4 bytes and not 16 bytes. if((mode == AES_MODE_CFB) || (mode == AES_MODE_OFB) || (mode == AES_MODE_CTR)) { for(j = 0; j < 4; j++){ // Writing the input data with zero-padding for(k = 0; k < 4; k++){ ENCDI = ((i + 4*j + k < length) ? pDataIn[i + 4*j + k] : 0x00 ); } // Read out data for every 4th byte for(k = 0; k < 4; k++){ pDataOut[i + 4*j + k] = ENCDO; } } } else if (mode == AES_MODE_CBCMAC){ // Writing the input data with zero-padding for(j = 0; j < 16; j++){ ENCDI = ((i + j < length) ? pDataIn[i + j] : 0x00 ); } // The last block of the CBC-MAC is computed by using CBC mode. if(convertedBlock == nbrOfBlocks - 2){ AES_SET_MODE(AES_MODE_CBC); // wait for data ready halMcuWaitUs(1); } // The CBC-MAC does not produce an output on the n-1 first blocks // only the last block is read out else if(convertedBlock == nbrOfBlocks - 1){ // wait for data ready halMcuWaitUs(1); for(j = 0; j < 16; j++){ pDataOut[j] = ENCDO; } } } // ECB or CBC else{ // Writing the input data with zero-padding for(j = 0; j < 16; j++){ ENCDI = ((i+j < length) ? pDataIn[i+j] : 0x00 ); } // wait for data ready halMcuWaitUs(1); // Read out data for(j = 0; j < 16; j++){ pDataOut[i+j] = ENCDO; } } } }
/*********************************************************************************** * @fn halMcuWaitMs * * @brief Busy wait function. Waits the specified number of milliseconds. Use * assumptions about number of clock cycles needed for the various * instructions. * * NB! This function is highly dependent on architecture and compiler! * * @param uint16 millisec - number of milliseconds delay * * @return none */ void halMcuWaitMs(uint16 msec) { while(msec--) halMcuWaitUs(1000); }