/** * @brief Writes several byte to the CC2500 registers. * @param pBuffer : pointer to the buffer containing the data to be written to the CC2500 registers. * @param WriteAddr : CC2500's internal address to write to. * @param NumByteToWrite: Number of bytes to write. * @retval None */ void CC2500_WriteRegister(uint8_t* pBuffer, uint8_t WriteAddr, uint16_t NumByteToWrite) { //set the first bit of header to 0 (write) //if multiple bytes to read, set the secodn bit of header to 1 (burst) if(NumByteToWrite > 0x01) { WriteAddr = (uint8_t) ((WriteAddr & CC2500_ADDRESS_MASK) | BURST_MODE); } else { WriteAddr = (uint8_t) (WriteAddr & CC2500_ADDRESS_MASK); } /* Set chip select Low at the start of the transmission */ if (CC2500_Chip_Select() == CC2500_TIMEOUT_ERROR) { //terminate the transaction and return CC2500_CS_HIGH(); return; } /* Send the Address of the indexed register */ CC2500_SendByte(WriteAddr); /* Send the data that will be written into the device (MSB First) */ while(NumByteToWrite >= 0x01) { CC2500_SendByte(*pBuffer); NumByteToWrite--; pBuffer++; } /* Set chip select High at the end of the transmission */ CC2500_CS_HIGH(); }
/** * @brief Writes one CC2500 Command. * @param WriteCommand : CC2500 Command. * @param ReadWriteFIFOFlag : 1: return RX FIFO available bytes; 0: return TX FIFO available bytes * @retval uint8_t status */ uint8_t CC2500_WriteCommand(uint8_t WriteCommand, uint8_t ReadWriteFIFOFlag) { uint8_t status; WriteCommand &= (uint8_t) CC2500_ADDRESS_MASK; if ((WriteCommand < 0x30) || (WriteCommand > 0x3D)) { return CC2500_STATUS_ERROR; } if (ReadWriteFIFOFlag) { WriteCommand |= (uint8_t) 0x80; } /* Set chip select Low at the start of the transmission */ if (CC2500_Chip_Select() == CC2500_TIMEOUT_ERROR) { //terminate the transaction and return CC2500_CS_HIGH(); return CC2500_STATUS_ERROR; } /* Send the Address of the indexed register */ status = CC2500_SendByte(WriteCommand); /* Set chip select High at the end of the transmission */ CC2500_CS_HIGH(); return status; }
/** * @brief Reads a block of data from the CC2500. * @param pBuffer : pointer to the buffer that receives the data read from the CC2500. * @param ReadAddr : CC2500's internal address to read from. * @param NumByteToRead : number of bytes to read from the CC2500. * @retval None */ void CC2500_Read(uint8_t* pBuffer, uint8_t ReadAddr, uint16_t NumByteToRead) { if(NumByteToRead > 0x01) { ReadAddr |= (uint8_t)(READWRITE_CMD | MULTIPLEBYTE_CMD); } else { ReadAddr |= (uint8_t)READWRITE_CMD; } /* Set chip select Low at the start of the transmission */ CC2500_CS_LOW(); /* Send the Address of the indexed register */ CC2500_SendByte(ReadAddr); /* Receive the data that will be read from the device (MSB First) */ while(NumByteToRead > 0x00) { /* Send dummy byte (0x00) to generate the SPI clock to CC2500 (Slave device) */ *pBuffer = CC2500_SendByte(DUMMY_BYTE); NumByteToRead--; pBuffer++; } /* Set chip select High at the end of the transmission */ CC2500_CS_HIGH(); }
/** * @brief Writes one byte to the CC2500. * @param pBuffer : pointer to the buffer containing the data to be written to the CC2500. * @param WriteAddr : CC2500's internal address to write to. * @param NumByteToWrite: Number of bytes to write. * @retval None */ void CC2500_Write(uint8_t* pBuffer, uint8_t WriteAddr, uint16_t NumByteToWrite) { /* Configure the MS bit: - When 0, the address will remain unchanged in multiple read/write commands. - When 1, the address will be auto incremented in multiple read/write commands. */ if(NumByteToWrite > 0x01) { WriteAddr |= (uint8_t)MULTIPLEBYTE_CMD; } /* Set chip select Low at the start of the transmission */ CC2500_CS_LOW(); /* Send the Address of the indexed register */ CC2500_SendByte(WriteAddr); /* Send the data that will be written into the device (MSB First) */ while(NumByteToWrite >= 0x01) { CC2500_SendByte(*pBuffer); NumByteToWrite--; pBuffer++; } /* Set chip select High at the end of the transmission */ CC2500_CS_HIGH(); }
/** * @brief Sends a single strobe command to CC2500 * @param Strobe command to send * @param 1 for the FIFO_BYTES_AVAILABLE field in status byte should be for the RX FIFO, 0 if it should be for the TX FIFO * @retval Status update received from CC2500 */ uint8_t CC2500_Strobe(StrobeCommand StrobeCmd, uint8_t RX_FIFO) { //Set the Chip Select to low at the beginning of the transmission (page 21, CC2500) CC2500_CS_LOW(); //The address we'll be writing to uint8_t StrobeAddr; //Check which FIFO status should be sent back with the status byte (page 24, CC2500) if(RX_FIFO){ //Set the read/write bit if we want the RX FIFO StrobeAddr = ((uint8_t)StrobeCmd) | READWRITE_BIT; } else{ //If not, just use the StrobeCmd address StrobeAddr = (uint8_t)StrobeCmd; } //Send the address of the register, get the response uint8_t statusByte = CC2500_SendByte(StrobeAddr); //Set the Chip Select to high at the end of the transmission //only for the SPWD and SXOFF strobes (page 24, CC2500) if(StrobeCmd == (CC2500_STROBE_SPWD || CC2500_STROBE_SXOFF)){ CC2500_CS_HIGH(); } //Return the response return statusByte; }
/** * @brief Writes bytes to the CC2500. * @param pBuffer : pointer to the buffer containing the data to be written to the CC2500. * @param WriteAddr : CC2500's internal address to write to. * @param NumByteToWrite: Number of bytes to write. * @retval None */ void CC2500_Write(uint8_t* pBuffer, uint8_t WriteAddr, uint16_t NumByteToWrite) {//Configure the header byte: burst access bit (B) and a 6-bit address (page 21, CC2500) //If more than one register needs to be written to, set B to 1 (page 23, CC2500) if(NumByteToWrite > 0x01){ WriteAddr |= BURST_BIT; } //Set the Chip Select to low at the beginning of the transmission (page 21, CC2500) CC2500_CS_LOW(); //Send the address of the register CC2500_SendByte(WriteAddr); //Then loop through all of the bytes that need ot be send (MSB first) while(NumByteToWrite > 0x00){ //Send the current byte at the pBuffer address CC2500_SendByte(*pBuffer); //Decrement the number of bytes to write NumByteToWrite--; //Increment the pBuffer pointer position pBuffer++; } //Set the Chip Select to high at the end of the transmission (page 23, CC2500) CC2500_CS_HIGH(); }
/** * @brief Reads a block of data from the CC2500. * @param pBuffer : pointer to the buffer that receives the data read from the CC2500. * @param ReadAddr : CC2500's internal address to read from. * @param NumByteToRead : number of bytes to read from the CC2500. * @retval None */ void CC2500_Read(uint8_t* pBuffer, uint8_t ReadAddr, uint16_t NumByteToRead) { //Configure the header byte: burst access bit (B) and a 6-bit address (page 21, CC2500) //If more than one register needs to be written to, set B to 1 (page 23, CC2500) //Regardless, set the read/write bit if(NumByteToRead > 0x01){ ReadAddr |= BURST_BIT | READWRITE_BIT; } else{ ReadAddr |= READWRITE_BIT; } //Set the Chip Select to low at the beginning of the transmission (page 21, CC2500) CC2500_CS_LOW(); //Send the address of the register CC2500_SendByte(ReadAddr); //Then loop through the number of bytes that need to be read (MSB first) while(NumByteToRead > 0x00){ //Send a dummy byte, store the response in the buffer *pBuffer = CC2500_SendByte(DUMMY_BYTE); //Decrement the number of bytes to read NumByteToRead--; //Increment the pBuffer pointer position pBuffer++; } //Set the Chip Select to high at the end of the transmission (page 23, CC2500) CC2500_CS_HIGH(); }
/** * @brief Sends command strobe to the CC2500. * @param cmd representing command strobe to be issued (see CC2500 UM page 60, table 37). * @param Pointer to the current state of the CC2500(before strobe was issued). * @param Pointer to number of free bytes in the CC2500 FIFO(before strobe was issued). * @retval None */ void CC2500_StrobeSend(uint8_t cmd, uint8_t* state, uint8_t* buffer_space) { uint8_t chip_status =0; /* Set chip select Low at the start of the transmission */ CC2500_CS_LOW(); /* Send the command and receive chip ststus byte, and extract the state (bytes 6:4) */ chip_status = CC2500_SendByte(cmd); /* Set chip select High at the end of the transmission */ CC2500_CS_HIGH(); // osDelay(10); // CC2500_CS_LOW(); // // /* Send the command and receive chip ststus byte, and extract the state (bytes 6:4) */ // chip_status = CC2500_SendByte(DUMMY_BYTE); // // /* Set chip select High at the end of the transmission */ // CC2500_CS_HIGH(); *state = chip_status & 0x70; *buffer_space = chip_status & 0x0F; }
/** * @brief Read status registor on he device * @param Address of the status register to read * @retval Status register bits received from CC2500 */ uint8_t CC2500_StatusReg(uint8_t StatusRegAddr) { uint8_t reg; //Set the Chip Select to low at the beginning of the transmission (page 21, CC2500) CC2500_CS_LOW(); // set burst bit to high to distinct from strobe command (page 5, cc2500 design note) StatusRegAddr |= BURST_BIT; CC2500_Read(®, StatusRegAddr, 1); // set the chip select to high marking end of transmission CC2500_CS_HIGH(); return reg; }
/** * @brief Reads a block of data from the CC2500 registers. * @param pBuffer : pointer to the buffer that receives the data read from the CC2500. * @param ReadAddr : CC2500's internal address to read from. * @param NumByteToRead : number of bytes to read from the CC2500 registers. * @retval None */ void CC2500_ReadRegister(uint8_t* pBuffer, uint8_t ReadAddr, uint16_t NumByteToRead) { ReadAddr = (uint8_t) (ReadAddr & CC2500_ADDRESS_MASK); //set the first bit of header to 1 (read) //if multiple bytes to read or read status registers, set the second bit of header to 1 (burst) if((NumByteToRead > 0x01) || ((ReadAddr >= 0x30) && (ReadAddr <=0x3D))) { ReadAddr |= (uint8_t) (READ_MODE | BURST_MODE); } else { ReadAddr |= (uint8_t) READ_MODE; } /* Set chip select Low at the start of the transmission */ if (CC2500_Chip_Select() == CC2500_TIMEOUT_ERROR) { //terminate the transaction and return CC2500_CS_HIGH(); return; } /* Send the Address of the indexed register */ CC2500_SendByte(ReadAddr); /* Receive the data that will be read from the device (MSB First) */ while(NumByteToRead > 0x00) { /* Send dummy byte (0x00) to generate the SPI clock to LIS302DL (Slave device) */ *pBuffer = CC2500_SendByte(DUMMY_BYTE); NumByteToRead--; pBuffer++; } /* Set chip select High at the end of the transmission */ CC2500_CS_HIGH(); }
void cc2500_One_Byte_Read(uint8_t* pBuffer, uint8_t ReadAddr) { /* Set chip select Low at the start of the transmission */ CC2500_CS_LOW(); /* Send the Address of the indexed register */ cc2500_SendByte(ReadAddr); /* Send dummy byte (0x00) to generate the SPI clock to cc2500 (Slave device) */ *pBuffer = cc2500_SendByte(DUMMY_BYTE); pBuffer++; /* Set chip select High at the end of the transmission */ CC2500_CS_HIGH(); }
/** * @brief Sends a command stobe to the wireless chipset. * * @retval The current state of the wireless chipset. */ uint8_t CC2500_Strobe(uint8_t Strobe){ // uint8_t *buff; // CC2500_CS_LOW(); // CC2500_SendByte(Strobe); // //Wait until SO goes high // CC2500_Read(buff, 0xBF, 0); // CC2500_CS_HIGH(); CC2500_CS_LOW(); while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE)== RESET); // check flag for transmission to be RESET SPI_I2S_SendData(SPI1, Strobe); // condition satisfied --> send command strobe while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET); // check flag for being busy to be SET CC2500_state = (SPI_I2S_ReceiveData(SPI1) & 0x70) >> 4; // set status to most recent received data on SPI1 // Set chip select High at the end of the transmission CC2500_CS_HIGH(); return CC2500_state; }
/** * @brief Reads a block of data from the CC2500. * @param pBuffer : pointer to the buffer that receives the data read from the CC2500. * @param ReadAddr : CC2500's internal address to read from. * @param NumByteToRead : number of bytes to read from the CC2500. * @retval None */ void CC2500_Read(uint8_t* pBuffer, uint8_t ReadAddr, uint16_t NumByteToRead) { if(NumByteToRead > 0x01) { //differentiate command strobes from status registers using burst mode //ie. must use burst mode to read status registers however chip will //only return single register (single byte access for status registers) //as a result, we check to see if the address is in the status register range, //if so, keep the burst bit so the chip interprets the right instruction, //but modify NumByteToRead to only expect single byte return if((ReadAddr >= 0x30) && (ReadAddr <= 0x3D)){ //address limits for status registers NumByteToRead = 0x01; } //0 is single op, 1 is burst ReadAddr |= (uint8_t)(READWRITE_CMD | MULTIPLEBYTE_CMD); } else { ReadAddr |= (uint8_t)READWRITE_CMD; } /* Set chip select Low at the start of the transmission */ CC2500_CS_LOW(); /* Send the Address of the indexed register */ *pBuffer = CC2500_SendByte(ReadAddr); /* Receive the data that will be read from the device (MSB First) */ while(NumByteToRead > 0x00) { /* Send dummy byte (0x00) to generate the SPI clock to LIS302DL (Slave device) */ *pBuffer = CC2500_SendByte(DUMMY_BYTE); NumByteToRead--; pBuffer++; } /* Set chip select High at the end of the transmission */ CC2500_CS_HIGH(); }
/** * @brief Configures the SPI and starts the wireless chipset. * * @notes Configures SPI with the pins defined in the CC2500.h file. Then uses * the SPI to put the wireless chipset through its manual restart * procedure. */ void CC2500_LowLevel_Init(void){ GPIO_InitTypeDef GPIO_InitStructure; SPI_InitTypeDef SPI_InitStructure; uint8_t ctrl; /* Enable the SPI periph */ RCC_APB2PeriphClockCmd(CC2500_SPI_CLK, ENABLE); /* Enable SCK, MOSI and MISO GPIO clocks */ RCC_AHB1PeriphClockCmd(CC2500_SPI_SCK_GPIO_CLK | CC2500_SPI_MISO_GPIO_CLK | CC2500_SPI_MOSI_GPIO_CLK, ENABLE); /* Enable CS GPIO clock */ RCC_AHB1PeriphClockCmd(CC2500_SPI_CS_GPIO_CLK, ENABLE); GPIO_PinAFConfig(CC2500_SPI_SCK_GPIO_PORT, CC2500_SPI_SCK_SOURCE, CC2500_SPI_SCK_AF); GPIO_PinAFConfig(CC2500_SPI_MISO_GPIO_PORT, CC2500_SPI_MISO_SOURCE, CC2500_SPI_MISO_AF); GPIO_PinAFConfig(CC2500_SPI_MOSI_GPIO_PORT, CC2500_SPI_MOSI_SOURCE, CC2500_SPI_MOSI_AF); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; /* SPI SCK pin configuration */ GPIO_InitStructure.GPIO_Pin = CC2500_SPI_SCK_PIN; GPIO_Init(CC2500_SPI_SCK_GPIO_PORT, &GPIO_InitStructure); /* SPI MOSI pin configuration */ GPIO_InitStructure.GPIO_Pin = CC2500_SPI_MOSI_PIN; GPIO_Init(CC2500_SPI_MOSI_GPIO_PORT, &GPIO_InitStructure); /* SPI MISO pin configuration */ GPIO_InitStructure.GPIO_Pin = CC2500_SPI_MISO_PIN; GPIO_Init(CC2500_SPI_MISO_GPIO_PORT, &GPIO_InitStructure); /* SPI configuration -------------------------------------------------------*/ SPI_I2S_DeInit(CC2500_SPI); SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_Init(CC2500_SPI, &SPI_InitStructure); /* Enable SPI1 */ SPI_Cmd(CC2500_SPI, ENABLE); /* Configure GPIO PIN for Lis Chip select */ GPIO_InitStructure.GPIO_Pin = CC2500_SPI_CS_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_Init(CC2500_SPI_CS_GPIO_PORT, &GPIO_InitStructure); /* Deselect : Chip Select high */ GPIO_SetBits(CC2500_SPI_CS_GPIO_PORT, CC2500_SPI_CS_PIN); //CC2500_Read(&ctrl, 0x30, 1); CC2500_CS_LOW(); delay(100); CC2500_CS_HIGH(); delay(100); CC2500_CS_LOW(); delay(150); // Send reset command CC2500_Strobe(SRES); while(!GPIO_ReadInputDataBit(CC2500_SPI_MISO_GPIO_PORT, CC2500_SPI_MISO_PIN)); CC2500_CS_HIGH(); // Set to IDLE state CC2500_Strobe(SIDLE); }
/** * @brief Initializes the low level interface used to drive the CC2500 * @param None * @retval None */ static void CC2500_LowLevel_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; SPI_InitTypeDef SPI_InitStructure; /* Enable the SPI periph */ RCC_APB1PeriphClockCmd(CC2500_SPI_CLK, ENABLE); /* Enable SCK, CS, INT, MOSI and MISO GPIO clocks */ RCC_AHB1PeriphClockCmd(CC2500_SPI_SCK_GPIO_CLK | CC2500_SPI_MISO_GPIO_CLK | CC2500_SPI_MOSI_GPIO_CLK | CC2500_SPI_CS_GPIO_CLK | CC2500_SPI_INT_GPIO_CLK, ENABLE); GPIO_PinAFConfig(CC2500_SPI_SCK_GPIO_PORT, CC2500_SPI_SCK_SOURCE, CC2500_SPI_SCK_AF); GPIO_PinAFConfig(CC2500_SPI_MISO_GPIO_PORT, CC2500_SPI_MISO_SOURCE, CC2500_SPI_MISO_AF); GPIO_PinAFConfig(CC2500_SPI_MOSI_GPIO_PORT, CC2500_SPI_MOSI_SOURCE, CC2500_SPI_MOSI_AF); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; /* SPI SCK pin configuration */ GPIO_InitStructure.GPIO_Pin = CC2500_SPI_SCK_PIN; GPIO_Init(CC2500_SPI_SCK_GPIO_PORT, &GPIO_InitStructure); /* SPI MOSI pin configuration */ GPIO_InitStructure.GPIO_Pin = CC2500_SPI_MOSI_PIN; GPIO_Init(CC2500_SPI_MOSI_GPIO_PORT, &GPIO_InitStructure); /* SPI MISO pin configuration */ GPIO_InitStructure.GPIO_Pin = CC2500_SPI_MISO_PIN; GPIO_Init(CC2500_SPI_MISO_GPIO_PORT, &GPIO_InitStructure); /* SPI configuration -------------------------------------------------------*/ SPI_I2S_DeInit(CC2500_SPI); SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_Init(CC2500_SPI, &SPI_InitStructure); /* Enable SPI1 */ SPI_Cmd(CC2500_SPI, ENABLE); /* Configure GPIO PIN for cc2500 Chip select */ GPIO_InitStructure.GPIO_Pin = CC2500_SPI_CS_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_Init(CC2500_SPI_CS_GPIO_PORT, &GPIO_InitStructure); /* Deselect : Chip Select high */ CC2500_CS_HIGH(); /* Configure GPIO PINs to detect Interrupts */ GPIO_InitStructure.GPIO_Pin = CC2500_SPI_INT_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(CC2500_SPI_INT_GPIO_PORT, &GPIO_InitStructure); }