/******************************************************************************* * @fn perCC1120CC1190Read8BitRssi * * @brief Reads MSB RSSI value from register, converts the dBm value to * decimal and adjusts it according to RSSI offset * * input parameters * * @param none * * output parameters * * @return decimal RSSI value corrected for RSSI offset */ int8 perCC1120CC1190Read8BitRssi(void) { uint8 rssi2compl,rssiValid; int16 rssiConverted; cc112xSpiReadReg(CC112X_RSSI0, &rssiValid,1); if(rssiValid & 0x01) { /* Read RSSI from MSB register */ cc112xSpiReadReg(CC112X_RSSI1, &rssi2compl,1); rssiConverted = (int8)((int8)rssi2compl) - cc1120cc1190RssiOffset; return rssiConverted; } /* keep last value since new value is not valid */ return rxData->rssi; }
/******************************************************************************* * @fn packetReceivedISR * * @brief Function running every time a packet has been received * * @param none * * @return none */ static void packetReceivedISR(void) { cc112xSpiReadRxFifo(pBufferIndex, bytesLeft); packetReceived = TRUE; cc112xSpiReadReg(CC112X_RSSI1,&rssi_readout,1); // Convert to decimal value from 2's complement rssi_readout. rssi = (int16)((int8)rssi_readout) - cc112xRssiOffset; // Clear ISR flag ioPinIntClear(IO_PIN_PORT_1, GPIO3); }
/****************************************************************************** * @fn perCC1120CC1190SetOutputPower * * @brief Configures the output power of CC112x according to the provided * index: * 0 = xx dBm * 1 = 26 dBm * NOTE: for PG2.0 pa_shape_en and pa_power_ramp has swapped * position * * * * input parameters * * @param index - index to table <=> wanted output level * * output parameters * * @return void */ void perCC1120CC1190SetOutputPower(uint8 index) { uint8 level; /* Reading the PA_CFG2 value to account for pa_shape_en */ cc112xSpiReadReg(CC112X_PA_CFG2,&level,1); /* Saving pa_shape_en */ level &= 0x40; /* Oring in the PA power ramp value */ level |= paPowerRamp[index]; /* Updating PA_CFG2 register with its' new value */ cc112xSpiWriteReg(CC112X_PA_CFG2,&level,1); return; }
/******************************************************************************* * @fn syncReceivedISR * * @brief Function running every time a sync word has been received * * @param none * * @return none */ static void syncReceivedISR(void) { uint8 numRxBytes; uint8 writeByte; // After the sync word is received one needs to wait for the two // length bytes to be put in the RX FIFO do { cc112xSpiReadReg(CC112X_NUM_RXBYTES, &numRxBytes, 1); } while (numRxBytes < 2); // Read the length byte and store it in the packetLength variable cc112xSpiReadRxFifo(rxBuffer, 2); pBufferIndex += 2; packetLength = (uint16)(((uint16)(rxBuffer[0] << 8)) | rxBuffer[1]); // Make sure that the packet length is in the correct range, update // variables and enable interrupt on falling edge of GPIO3 (PKT_SYNC_RXTX) if ((packetLength > MAX_VARIABLE_LENGTH) && (packetLength <= PACKET_LENGTH)) { bytesLeft = packetLength + 2; fixedPacketLength = bytesLeft % (MAX_VARIABLE_LENGTH + 1); writeByte = fixedPacketLength; cc112xSpiWriteReg(CC112X_PKT_LEN, &writeByte, 1); // Clear interrupt flag and enable GPIO3 ioPinIntClear(IO_PIN_PORT_1, GPIO3); ioPinIntEnable(IO_PIN_PORT_1, GPIO3); } else { // Exit RX and flush RX FIFO due to length byte being out of range trxSpiCmdStrobe(CC112X_SIDLE); trxSpiCmdStrobe(CC112X_SFRX); state = RX_START; } // Clear ISR flag ioPinIntClear(IO_PIN_PORT_1, GPIO2); }
void cc112x_event_handler_test(void) { uint8_t part_num = 0; cc112x_init(); GPIO_ResetBits(GPIO_PORT_CC112X_RESET, GPIO_PIN_CC112X_RESET); delay1ms(1); GPIO_SetBits(GPIO_PORT_CC112X_RESET, GPIO_PIN_CC112X_RESET); /* Power Up Reset */ rf_PowerUpReset(); registerConfig(); #ifdef CC112x_DEBUG printf("[CC112X] registerConfiging OK...\r\n"); #endif cc112xSpiReadReg(CC112X_PARTNUMBER, &part_num, 1); #ifdef CC112x_DEBUG printf("[CC112X] cc112xSpiReadReg,part_num = 0x%02x\r\n",part_num); #endif }
/****************************************************************************** * @fn perCC1120CC1190RxTxISR * * @brief ISR that's called when sync signal goes low. * In RX State: Filters incoming data. The global rxData pointer * always points to this functions static rxData_tmp(struct of * same kind). The validnes of rxData fields is indicated by the * the global flag packetSemaphore. * In TX State: Nothing is done except it facilitates power * consumption reduction when TX since the program doesn't need * to wait until TX is done before re-enabling sync pin interrupt. * cc1120cc1190RadioTxRx is also set to CC112X_STATE_IDLE to be consistent * with program. * * input parameters * * @param none * * output parameters * * @return void */ void perCC1120CC1190RxTxISR(void) { uint8 rxBytes,rxLength,rssiIndex,lqiIndex; /* This variable stores the data locally. Access is given to per_test by * assigning this instance to the global rxData pointer */ static rxData_t rxData_tmp; rxData = &rxData_tmp; /* Checking if the chip is in RX state: */ if(cc1120cc1190RadioTxRx != CC112X_STATE_RX) { /* Transmission finished */ if((perSettings.deviceMode == MASTER_DEVICE) && (perSettings.linkTopology == LINK_2_WAY) && (perSettings.masterSlaveLinked ==PER_DEVICE_LINKED)) { /* Only applicable when master in 2-way test */ cc1120cc1190RadioTxRx=CC112X_STATE_RX; } else { cc1120cc1190RadioTxRx = CC112X_STATE_IDLE; } return; } packetSemaphore |= SYNC_FOUND; if(((perSettings.masterSlaveLinked == PER_DEVICE_LINKED)||(perSettings.masterSlaveLinked == PER_DEVICE_LINK_BYPASS)) && (perSettings.deviceMode == MASTER_DEVICE) && (perSettings.testRunning == PER_TRUE)) { if(perSettings.linkTopology == LINK_1_WAY) { /* Read timer value and set the perSettings.packetRate valu(adjustment for temperature drift */ halTimer32kSetIntFrequency(perSettings.packetRate); halTimer32kIntEnable(); } else { /* LINK_2_WAY */ /* Timeout interrupt configuring is handled by the 2-way Per test */ timer32kValue = halTimer32kReadTimerValue(); halTimer32kAbort(); } } cc112xSpiReadReg(CC112X_NUM_RXBYTES,&rxBytes,1); /* Checking if the FIFO is empty */ if(rxBytes == PER_FALSE) { /* The packet was removed by HW due to addr or length filtering -> Do nothing */ /* Report that a sync was detected */ rxData_tmp.rssi = perCC1120CC1190Read8BitRssi(); return; } else { /* The RX FIFO is not empty, process contents */ cc112xSpiReadRxFifo(&rxLength, 1); /* Check that the packet length just read + FCS(2B) + length byte match the RXBYTES */ /* If these are not equal: * - RXFIFO overflow: Received packets not processed while beeing in RX. */ if(rxBytes != (rxLength+3)) { /* This is a fault FIFO condition -> clean FIFO and register a sync detection */ /* IDLE -> FLUSH RX FIFO -> RX */ cc1120cc1190RxIdle(); perCC1120CC1190EnterRx(); /* Report that a sync was detected */ rxData_tmp.rssi = perCC1120CC1190Read8BitRssi(); return; } else { /* We don't have a FIFO error condition -> get packet */ /* Length Field */ rxData_tmp.data[0] = rxLength; rssiIndex = rxLength+1; lqiIndex = rssiIndex +1; /* Payload(ADDR + DATA + FCS) */ cc112xSpiReadRxFifo(&rxData_tmp.data[1], lqiIndex); /* The whole packet has been read from the FIFO. * Check if the CRC is correct and that the packet length is as expected. * If not correct: report sync found and do not update RSSI or LQI. */ if((!(rxData_tmp.data[lqiIndex] & CC112X_LQI_CRC_OK_BM)) || (perSettings.payloadLength != rxLength )) { rxData_tmp.rssi = perCC1120CC1190Read8BitRssi(); return; } /* A complete error-free packet has arrived */ /* Measured data */ rxData_tmp.length = rxLength; rxData_tmp.lqi = rxData_tmp.data[lqiIndex] & CC112X_LQI_EST_BM; rxData_tmp.addr = rxData_tmp.data[1]; /* Convert RSSI value from 2's complement to decimal value accounting for offset value */ rxBytes = rxData_tmp.data[rssiIndex]; rxData_tmp.rssi = (int8)((int8)rxBytes) - cc1120cc1190RssiOffset; /* Signal a good packet is received */ packetSemaphore |= PACKET_RECEIVED; return; } } }
/******************************************************************************* * @fn manualCalibration * * @brief Perform manual calibration according to the errata note * @param none * * @return none */ static void manualCalibration(void) { uint8 original_fs_cal2; uint8 calResults_for_vcdac_start_high[3]; uint8 calResults_for_vcdac_start_mid[3]; uint8 marcstate; uint8 writeByte; // 1) Set VCO cap-array to 0 (FS_VCO2 = 0x00) writeByte = 0x00; cc112xSpiWriteReg(CC112X_FS_VCO2, &writeByte, 1); // 2) Start with high VCDAC (original VCDAC_START + 2): cc112xSpiReadReg(CC112X_FS_CAL2, &original_fs_cal2, 1); writeByte = original_fs_cal2 + VCDAC_START_OFFSET; cc112xSpiWriteReg(CC112X_FS_CAL2, &writeByte, 1); // 3) Calibrate and wait for calibration to be done (radio back in IDLE state) trxSpiCmdStrobe(CC112X_SCAL); do { cc112xSpiReadReg(CC112X_MARCSTATE, &marcstate, 1); } while (marcstate != 0x41); // 4) Read FS_VCO2, FS_VCO4 and FS_CHP register obtained with high VCDAC_START value cc112xSpiReadReg(CC112X_FS_VCO2, &calResults_for_vcdac_start_high[FS_VCO2_INDEX], 1); cc112xSpiReadReg(CC112X_FS_VCO4, &calResults_for_vcdac_start_high[FS_VCO4_INDEX], 1); cc112xSpiReadReg(CC112X_FS_CHP, &calResults_for_vcdac_start_high[FS_CHP_INDEX], 1); // 5) Set VCO cap-array to 0 (FS_VCO2 = 0x00) writeByte = 0x00; cc112xSpiWriteReg(CC112X_FS_VCO2, &writeByte, 1); // 6) Continue with mid VCDAC (original VCDAC_START): writeByte = original_fs_cal2; cc112xSpiWriteReg(CC112X_FS_CAL2, &writeByte, 1); // 7) Calibrate and wait for calibration to be done (radio back in IDLE state) trxSpiCmdStrobe(CC112X_SCAL); do { cc112xSpiReadReg(CC112X_MARCSTATE, &marcstate, 1); } while (marcstate != 0x41); // 8) Read FS_VCO2, FS_VCO4 and FS_CHP register obtained with mid VCDAC_START value cc112xSpiReadReg(CC112X_FS_VCO2, &calResults_for_vcdac_start_mid[FS_VCO2_INDEX], 1); cc112xSpiReadReg(CC112X_FS_VCO4, &calResults_for_vcdac_start_mid[FS_VCO4_INDEX], 1); cc112xSpiReadReg(CC112X_FS_CHP, &calResults_for_vcdac_start_mid[FS_CHP_INDEX], 1); // 9) Write back highest FS_VCO2 and corresponding FS_VCO and FS_CHP result if (calResults_for_vcdac_start_high[FS_VCO2_INDEX] > calResults_for_vcdac_start_mid[FS_VCO2_INDEX]) { writeByte = calResults_for_vcdac_start_high[FS_VCO2_INDEX]; cc112xSpiWriteReg(CC112X_FS_VCO2, &writeByte, 1); writeByte = calResults_for_vcdac_start_high[FS_VCO4_INDEX]; cc112xSpiWriteReg(CC112X_FS_VCO4, &writeByte, 1); writeByte = calResults_for_vcdac_start_high[FS_CHP_INDEX]; cc112xSpiWriteReg(CC112X_FS_CHP, &writeByte, 1); } else { writeByte = calResults_for_vcdac_start_mid[FS_VCO2_INDEX]; cc112xSpiWriteReg(CC112X_FS_VCO2, &writeByte, 1); writeByte = calResults_for_vcdac_start_mid[FS_VCO4_INDEX]; cc112xSpiWriteReg(CC112X_FS_VCO4, &writeByte, 1); writeByte = calResults_for_vcdac_start_mid[FS_CHP_INDEX]; cc112xSpiWriteReg(CC112X_FS_CHP, &writeByte, 1); } }
/*********************************************************************** * @brief Deal with the event handler for cc112x. * @param p_event_data * @param event_size * @retval None ************************************************************************/ void cc112x_event_handler(void * p_event_data, uint16_t event_size) { cc112x_event_t * p_cc112x_event_temp = p_event_data; uint8_t part_num = 0; uint8_t i,readByte; switch(p_cc112x_event_temp->eCC112x_event) { case CC112X_INIT_EVENT: #ifdef CC112x_DEBUG printf("[CC112X] CC112X_INIT_EVENT...\r\n"); #endif cc112x_init(); GPIO_ResetBits(GPIO_PORT_CC112X_RESET, GPIO_PIN_CC112X_RESET); delay1ms(1); GPIO_SetBits(GPIO_PORT_CC112X_RESET, GPIO_PIN_CC112X_RESET); // Power Up Reset rf_PowerUpReset(); registerConfig(); #ifdef CC112x_DEBUG printf("[CC112X] registerConfiging OK...\r\n"); cc112xSpiReadReg(CC112X_PARTNUMBER, &part_num, 1); printf("[CC112X] cc112xSpiReadReg,part_num = 0x%02x\r\n",part_num); #endif SPI_DeInit(APP_CC112X_SPI); GPIO_DeInit(GPIO_PORT_CC112X_SPI_NSS); break; case CC112X_TRANSMIT_EVENT: #ifdef CC112x_DEBUG printf("[CC112X] CC112X_TRANSMIT_EVENT...\r\n"); #endif trxRfSpiInterfaceInit(); #ifdef CC112x_DEBUG printf("[CC112X] cc112xSpiReadReg,part_num = 0x%02x\r\n",part_num); for(i = 0;i < (sizeof(preferredSettings)/sizeof(registerSetting_t)); i++) { cc112xSpiReadReg(preferredSettings[i].addr, &readByte, 1); printf("[CC112X] i = %d : 0x%02x \r\n",i,readByte); } #endif SPI_DeInit(APP_CC112X_SPI); GPIO_DeInit(GPIO_PORT_CC112X_SPI_NSS); break; case CC112X_RECEIVE_EVENT: trxRfSpiInterfaceInit(); #ifdef CC112x_DEBUG cc112xSpiReadReg(CC112X_PARTNUMBER, &part_num, 1); printf("[CC112X] cc112xSpiReadReg,part_num = 0x%02x\r\n",part_num); for(i = 0;i < (sizeof(preferredSettings)/sizeof(registerSetting_t)); i++) { cc112xSpiReadReg(preferredSettings[i].addr, &readByte, 1); printf("[CC112X] i = %d : 0x%02x \r\n",i,readByte); } #endif SPI_DeInit(APP_CC112X_SPI); GPIO_DeInit(GPIO_PORT_CC112X_SPI_NSS); break; default: break; } }