Skip to content
/*!
* File:
* si446x_api_lib.c
*
* Description:
* This file contains the Si446x API library.
*
* Silicon Laboratories Confidential
* Copyright 2011 Silicon Laboratories, Inc.
*/
#include "..\..\..\bsp.h"
#include <stdarg.h>
SEGMENT_VARIABLE( Si446xCmd, union si446x_cmd_reply_union, SEG_XDATA );
SEGMENT_VARIABLE( Pro2Cmd[16], U8, SEG_XDATA );
#ifdef SI446X_PATCH_CMDS
SEGMENT_VARIABLE( Si446xPatchCommands[][8] = { SI446X_PATCH_CMDS }, U8, SEG_CODE);
#endif
/*!
* This functions is used to reset the si446x radio by applying shutdown and
* releasing it. After this function @ref si446x_boot should be called. You
* can check if POR has completed by waiting 4 ms or by polling GPIO 0, 2, or 3.
* When these GPIOs are high, it is safe to call @ref si446x_boot.
*/
void si446x_reset(void)
{
U8 loopCount;
/* Put radio in shutdown, wait then release */
radio_hal_AssertShutdown();
//! @todo this needs to be a better delay function.
for (loopCount = 255; loopCount != 0; loopCount--);
radio_hal_DeassertShutdown();
for (loopCount = 255; loopCount != 0; loopCount--);
radio_comm_ClearCTS();
}
/*!
* This function is used to initialize after power-up the radio chip.
* Before this function @si446x_reset should be called.
*/
void si446x_power_up(U8 BOOT_OPTIONS, U8 XTAL_OPTIONS, U32 XO_FREQ)
{
Pro2Cmd[0] = SI446X_CMD_ID_POWER_UP;
Pro2Cmd[1] = BOOT_OPTIONS;
Pro2Cmd[2] = XTAL_OPTIONS;
Pro2Cmd[3] = (U8)(XO_FREQ >> 24);
Pro2Cmd[4] = (U8)(XO_FREQ >> 16);
Pro2Cmd[5] = (U8)(XO_FREQ >> 8);
Pro2Cmd[6] = (U8)(XO_FREQ);
radio_comm_SendCmd( SI446X_CMD_ARG_COUNT_POWER_UP, Pro2Cmd );
}
/*!
* This function is used to load all properties and commands with a list of NULL terminated commands.
* Before this function @si446x_reset should be called.
*/
U8 si446x_configuration_init(const U8* pSetPropCmd)
{
SEGMENT_VARIABLE(col, U8, SEG_DATA);
SEGMENT_VARIABLE(numOfBytes, U8, SEG_DATA);
/* While cycle as far as the pointer points to a command */
while (*pSetPropCmd != 0x00)
{
/* Commands structure in the array:
* --------------------------------
* LEN | <LEN length of data>
*/
numOfBytes = *pSetPropCmd++;
if (numOfBytes > 16u)
{
/* Number of command bytes exceeds maximal allowable length */
return SI446X_COMMAND_ERROR;
}
for (col = 0u; col < numOfBytes; col++)
{
Pro2Cmd[col] = *pSetPropCmd;
pSetPropCmd++;
}
if (radio_comm_SendCmdGetResp(numOfBytes, Pro2Cmd, 0, 0) != 0xFF)
{
/* Timeout occured */
return SI446X_CTS_TIMEOUT;
}
if (radio_hal_NirqLevel() == 0)
{
/* Get and clear all interrupts. An error has occured... */
si446x_get_int_status(0, 0, 0);
if (Si446xCmd.GET_INT_STATUS.CHIP_PEND & SI446X_CMD_GET_CHIP_STATUS_REP_CHIP_PEND_CMD_ERROR_PEND_MASK)
{
return SI446X_COMMAND_ERROR;
}
}
}
return SI446X_SUCCESS;
}
/*! This function sends the PART_INFO command to the radio and receives the answer
* into @Si446xCmd union.
*/
void si446x_part_info(void)
{
Pro2Cmd[0] = SI446X_CMD_ID_PART_INFO;
radio_comm_SendCmdGetResp( SI446X_CMD_ARG_COUNT_PART_INFO,
Pro2Cmd,
SI446X_CMD_REPLY_COUNT_PART_INFO,
Pro2Cmd );
Si446xCmd.PART_INFO.CHIPREV = Pro2Cmd[0];
Si446xCmd.PART_INFO.PART = ((U16)Pro2Cmd[1] << 8) & 0xFF00;
Si446xCmd.PART_INFO.PART |= (U16)Pro2Cmd[2] & 0x00FF;
Si446xCmd.PART_INFO.PBUILD = Pro2Cmd[3];
Si446xCmd.PART_INFO.ID = ((U16)Pro2Cmd[4] << 8) & 0xFF00;
Si446xCmd.PART_INFO.ID |= (U16)Pro2Cmd[5] & 0x00FF;
Si446xCmd.PART_INFO.CUSTOMER = Pro2Cmd[6];
Si446xCmd.PART_INFO.ROMID = Pro2Cmd[7];
}
/*! Sends START_TX command to the radio.
*
* @param CHANNEL Channel number.
* @param CONDITION Start TX condition.
* @param TX_LEN Payload length (exclude the PH generated CRC).
*/
void si446x_start_tx(U8 CHANNEL, U8 CONDITION, U16 TX_LEN)
{
Pro2Cmd[0] = SI446X_CMD_ID_START_TX;
Pro2Cmd[1] = CHANNEL;
Pro2Cmd[2] = CONDITION;
Pro2Cmd[3] = (U8)(TX_LEN >> 8);
Pro2Cmd[4] = (U8)(TX_LEN);
Pro2Cmd[5] = 0x00;
// Don't repeat the packet,
// ie. transmit the packet only once
Pro2Cmd[6] = 0x00;
radio_comm_SendCmd( SI446X_CMD_ARG_COUNT_START_TX, Pro2Cmd );
}
/*!
* Sends START_RX command to the radio.
*
* @param CHANNEL Channel number.
* @param CONDITION Start RX condition.
* @param RX_LEN Payload length (exclude the PH generated CRC).
* @param NEXT_STATE1 Next state when Preamble Timeout occurs.
* @param NEXT_STATE2 Next state when a valid packet received.
* @param NEXT_STATE3 Next state when invalid packet received (e.g. CRC error).
*/
void si446x_start_rx(U8 CHANNEL, U8 CONDITION, U16 RX_LEN, U8 NEXT_STATE1, U8 NEXT_STATE2, U8 NEXT_STATE3)
{
Pro2Cmd[0] = SI446X_CMD_ID_START_RX;
Pro2Cmd[1] = CHANNEL;
Pro2Cmd[2] = CONDITION;
Pro2Cmd[3] = (U8)(RX_LEN >> 8);
Pro2Cmd[4] = (U8)(RX_LEN);
Pro2Cmd[5] = NEXT_STATE1;
Pro2Cmd[6] = NEXT_STATE2;
Pro2Cmd[7] = NEXT_STATE3;
radio_comm_SendCmd( SI446X_CMD_ARG_COUNT_START_RX, Pro2Cmd );
}
/*!
* Get the Interrupt status/pending flags form the radio and clear flags if requested.
*
* @param PH_CLR_PEND Packet Handler pending flags clear.
* @param MODEM_CLR_PEND Modem Status pending flags clear.
* @param CHIP_CLR_PEND Chip State pending flags clear.
*/
void si446x_get_int_status(U8 PH_CLR_PEND, U8 MODEM_CLR_PEND, U8 CHIP_CLR_PEND)
{
Pro2Cmd[0] = SI446X_CMD_ID_GET_INT_STATUS;
Pro2Cmd[1] = PH_CLR_PEND;
Pro2Cmd[2] = MODEM_CLR_PEND;
Pro2Cmd[3] = CHIP_CLR_PEND;
radio_comm_SendCmdGetResp( SI446X_CMD_ARG_COUNT_GET_INT_STATUS,
Pro2Cmd,
SI446X_CMD_REPLY_COUNT_GET_INT_STATUS,
Pro2Cmd );
Si446xCmd.GET_INT_STATUS.INT_PEND = Pro2Cmd[0];
Si446xCmd.GET_INT_STATUS.INT_STATUS = Pro2Cmd[1];
Si446xCmd.GET_INT_STATUS.PH_PEND = Pro2Cmd[2];
Si446xCmd.GET_INT_STATUS.PH_STATUS = Pro2Cmd[3];
Si446xCmd.GET_INT_STATUS.MODEM_PEND = Pro2Cmd[4];
Si446xCmd.GET_INT_STATUS.MODEM_STATUS = Pro2Cmd[5];
Si446xCmd.GET_INT_STATUS.CHIP_PEND = Pro2Cmd[6];
Si446xCmd.GET_INT_STATUS.CHIP_STATUS = Pro2Cmd[7];
}
/*!
* Send GPIO pin config command to the radio and reads the answer into
* @Si446xCmd union.
*
* @param GPIO0 GPIO0 configuration.
* @param GPIO1 GPIO1 configuration.
* @param GPIO2 GPIO2 configuration.
* @param GPIO3 GPIO3 configuration.
* @param NIRQ NIRQ configuration.
* @param SDO SDO configuration.
* @param GEN_CONFIG General pin configuration.
*/
void si446x_gpio_pin_cfg(U8 GPIO0, U8 GPIO1, U8 GPIO2, U8 GPIO3, U8 NIRQ, U8 SDO, U8 GEN_CONFIG)
{
Pro2Cmd[0] = SI446X_CMD_ID_GPIO_PIN_CFG;
Pro2Cmd[1] = GPIO0;
Pro2Cmd[2] = GPIO1;
Pro2Cmd[3] = GPIO2;
Pro2Cmd[4] = GPIO3;
Pro2Cmd[5] = NIRQ;
Pro2Cmd[6] = SDO;
Pro2Cmd[7] = GEN_CONFIG;
radio_comm_SendCmdGetResp( SI446X_CMD_ARG_COUNT_GPIO_PIN_CFG,
Pro2Cmd,
SI446X_CMD_REPLY_COUNT_GPIO_PIN_CFG,
Pro2Cmd );
Si446xCmd.GPIO_PIN_CFG.GPIO[0] = Pro2Cmd[0];
Si446xCmd.GPIO_PIN_CFG.GPIO[1] = Pro2Cmd[1];
Si446xCmd.GPIO_PIN_CFG.GPIO[2] = Pro2Cmd[2];
Si446xCmd.GPIO_PIN_CFG.GPIO[3] = Pro2Cmd[3];
Si446xCmd.GPIO_PIN_CFG.NIRQ = Pro2Cmd[4];
Si446xCmd.GPIO_PIN_CFG.SDO = Pro2Cmd[5];
Si446xCmd.GPIO_PIN_CFG.GEN_CONFIG = Pro2Cmd[6];
}
/*!
* Send SET_PROPERTY command to the radio.
*
* @param GROUP Property group.
* @param NUM_PROPS Number of property to be set. The properties must be in ascending order
* in their sub-property aspect. Max. 12 properties can be set in one command.
* @param START_PROP Start sub-property address.
*/
#ifdef __C51__
#pragma maxargs (13) /* allow 13 bytes for parameters */
#endif
void si446x_set_property( U8 GROUP, U8 NUM_PROPS, U8 START_PROP, ... )
{
va_list argList;
U8 cmdIndex;
Pro2Cmd[0] = SI446X_CMD_ID_SET_PROPERTY;
Pro2Cmd[1] = GROUP;
Pro2Cmd[2] = NUM_PROPS;
Pro2Cmd[3] = START_PROP;
va_start (argList, START_PROP);
cmdIndex = 4;
while(NUM_PROPS--)
{
Pro2Cmd[cmdIndex] = va_arg (argList, U8);
cmdIndex++;
}
va_end(argList);
radio_comm_SendCmd( cmdIndex, Pro2Cmd );
}
/*!
* Issue a change state command to the radio.
*
* @param NEXT_STATE1 Next state.
*/
void si446x_change_state(U8 NEXT_STATE1)
{
Pro2Cmd[0] = SI446X_CMD_ID_CHANGE_STATE;
Pro2Cmd[1] = NEXT_STATE1;
radio_comm_SendCmd( SI446X_CMD_ARG_COUNT_CHANGE_STATE, Pro2Cmd );
}
#ifdef RADIO_DRIVER_EXTENDED_SUPPORT
/* Extended driver support functions */
/*!
* Sends NOP command to the radio. Can be used to maintain SPI communication.
*/
void si446x_nop(void)
{
Pro2Cmd[0] = SI446X_CMD_ID_NOP;
radio_comm_SendCmd( SI446X_CMD_ARG_COUNT_NOP, Pro2Cmd );
}
/*!
* Send the FIFO_INFO command to the radio. Optionally resets the TX/RX FIFO. Reads the radio response back
* into @Si446xCmd.
*
* @param FIFO RX/TX FIFO reset flags.
*/
void si446x_fifo_info(U8 FIFO)
{
Pro2Cmd[0] = SI446X_CMD_ID_FIFO_INFO;
Pro2Cmd[1] = FIFO;
radio_comm_SendCmdGetResp( SI446X_CMD_ARG_COUNT_FIFO_INFO,
Pro2Cmd,
SI446X_CMD_REPLY_COUNT_FIFO_INFO,
Pro2Cmd );
Si446xCmd.FIFO_INFO.RX_FIFO_COUNT = Pro2Cmd[0];
Si446xCmd.FIFO_INFO.TX_FIFO_SPACE = Pro2Cmd[1];
}
/*!
* The function can be used to load data into TX FIFO.
*
* @param numBytes Data length to be load.
* @param pTxData Pointer to the data (U8*).
*/
void si446x_write_tx_fifo(U8 numBytes, U8* pTxData)
{
radio_comm_WriteData( SI446X_CMD_ID_WRITE_TX_FIFO, 0, numBytes, pTxData );
}
/*!
* Reads the RX FIFO content from the radio.
*
* @param numBytes Data length to be read.
* @param pRxData Pointer to the buffer location.
*/
void si446x_read_rx_fifo(U8 numBytes, U8* pRxData)
{
radio_comm_ReadData( SI446X_CMD_ID_READ_RX_FIFO, 0, numBytes, pRxData );
}
/*!
* Get property values from the radio. Reads them into Si446xCmd union.
*
* @param GROUP Property group number.
* @param NUM_PROPS Number of properties to be read.
* @param START_PROP Starting sub-property number.
*/
void si446x_get_property(U8 GROUP, U8 NUM_PROPS, U8 START_PROP)
{
Pro2Cmd[0] = SI446X_CMD_ID_GET_PROPERTY;
Pro2Cmd[1] = GROUP;
Pro2Cmd[2] = NUM_PROPS;
Pro2Cmd[3] = START_PROP;
radio_comm_SendCmdGetResp( SI446X_CMD_ARG_COUNT_GET_PROPERTY,
Pro2Cmd,
Pro2Cmd[2],
Pro2Cmd );
Si446xCmd.GET_PROPERTY.DATA[0 ] = Pro2Cmd[0];
Si446xCmd.GET_PROPERTY.DATA[1 ] = Pro2Cmd[1];
Si446xCmd.GET_PROPERTY.DATA[2 ] = Pro2Cmd[2];
Si446xCmd.GET_PROPERTY.DATA[3 ] = Pro2Cmd[3];
Si446xCmd.GET_PROPERTY.DATA[4 ] = Pro2Cmd[4];
Si446xCmd.GET_PROPERTY.DATA[5 ] = Pro2Cmd[5];
Si446xCmd.GET_PROPERTY.DATA[6 ] = Pro2Cmd[6];
Si446xCmd.GET_PROPERTY.DATA[7 ] = Pro2Cmd[7];
Si446xCmd.GET_PROPERTY.DATA[8 ] = Pro2Cmd[8];
Si446xCmd.GET_PROPERTY.DATA[9 ] = Pro2Cmd[9];
Si446xCmd.GET_PROPERTY.DATA[10] = Pro2Cmd[10];
Si446xCmd.GET_PROPERTY.DATA[11] = Pro2Cmd[11];
Si446xCmd.GET_PROPERTY.DATA[12] = Pro2Cmd[12];
Si446xCmd.GET_PROPERTY.DATA[13] = Pro2Cmd[13];
Si446xCmd.GET_PROPERTY.DATA[14] = Pro2Cmd[14];
Si446xCmd.GET_PROPERTY.DATA[15] = Pro2Cmd[15];
}
#ifdef RADIO_DRIVER_FULL_SUPPORT
/* Full driver support functions */
/*!
* Sends the FUNC_INFO command to the radio, then reads the resonse into @Si446xCmd union.
*/
void si446x_func_info(void)
{
Pro2Cmd[0] = SI446X_CMD_ID_FUNC_INFO;
radio_comm_SendCmdGetResp( SI446X_CMD_ARG_COUNT_FUNC_INFO,
Pro2Cmd,
SI446X_CMD_REPLY_COUNT_FUNC_INFO,
Pro2Cmd );
Si446xCmd.FUNC_INFO.REVEXT = Pro2Cmd[0];
Si446xCmd.FUNC_INFO.REVBRANCH = Pro2Cmd[1];
Si446xCmd.FUNC_INFO.REVINT = Pro2Cmd[2];
Si446xCmd.FUNC_INFO.FUNC = Pro2Cmd[5];
}
/*!
* Reads the Fast Response Registers starting with A register into @Si446xCmd union.
*
* @param respByteCount Number of Fast Response Registers to be read.
*/
void si446x_frr_a_read(U8 respByteCount)
{
radio_comm_ReadData(SI446X_CMD_ID_FRR_A_READ,
0,
respByteCount,
Pro2Cmd);
Si446xCmd.FRR_A_READ.FRR_A_VALUE = Pro2Cmd[0];
Si446xCmd.FRR_A_READ.FRR_B_VALUE = Pro2Cmd[1];
Si446xCmd.FRR_A_READ.FRR_C_VALUE = Pro2Cmd[2];
Si446xCmd.FRR_A_READ.FRR_D_VALUE = Pro2Cmd[3];
}
/*!
* Reads the Fast Response Registers starting with B register into @Si446xCmd union.
*
* @param respByteCount Number of Fast Response Registers to be read.
*/
void si446x_frr_b_read(U8 respByteCount)
{
radio_comm_ReadData(SI446X_CMD_ID_FRR_B_READ,
0,
respByteCount,
Pro2Cmd);
Si446xCmd.FRR_B_READ.FRR_B_VALUE = Pro2Cmd[0];
Si446xCmd.FRR_B_READ.FRR_C_VALUE = Pro2Cmd[1];
Si446xCmd.FRR_B_READ.FRR_D_VALUE = Pro2Cmd[2];
Si446xCmd.FRR_B_READ.FRR_A_VALUE = Pro2Cmd[3];
}
/*!
* Reads the Fast Response Registers starting with C register into @Si446xCmd union.
*
* @param respByteCount Number of Fast Response Registers to be read.
*/
void si446x_frr_c_read(U8 respByteCount)
{
radio_comm_ReadData(SI446X_CMD_ID_FRR_C_READ,
0,
respByteCount,
Pro2Cmd);
Si446xCmd.FRR_C_READ.FRR_C_VALUE = Pro2Cmd[0];
Si446xCmd.FRR_C_READ.FRR_D_VALUE = Pro2Cmd[1];
Si446xCmd.FRR_C_READ.FRR_A_VALUE = Pro2Cmd[2];
Si446xCmd.FRR_C_READ.FRR_B_VALUE = Pro2Cmd[3];
}
/*!
* Reads the Fast Response Registers starting with D register into @Si446xCmd union.
*
* @param respByteCount Number of Fast Response Registers to be read.
*/
void si446x_frr_d_read(U8 respByteCount)
{
radio_comm_ReadData(SI446X_CMD_ID_FRR_D_READ,
0,
respByteCount,
Pro2Cmd);
Si446xCmd.FRR_D_READ.FRR_D_VALUE = Pro2Cmd[0];
Si446xCmd.FRR_D_READ.FRR_A_VALUE = Pro2Cmd[1];
Si446xCmd.FRR_D_READ.FRR_B_VALUE = Pro2Cmd[2];
Si446xCmd.FRR_D_READ.FRR_C_VALUE = Pro2Cmd[3];
}
/*!
* Reads the ADC values from the radio into @Si446xCmd union.
*
* @param ADC_EN ADC enable parameter.
*/
void si446x_get_adc_reading(U8 ADC_EN)
{
Pro2Cmd[0] = SI446X_CMD_ID_GET_ADC_READING;
Pro2Cmd[1] = ADC_EN;
radio_comm_SendCmdGetResp( SI446X_CMD_ARG_COUNT_GET_ADC_READING,
Pro2Cmd,
SI446X_CMD_REPLY_COUNT_GET_ADC_READING,
Pro2Cmd );
Si446xCmd.GET_ADC_READING.GPIO_ADC = ((U16)Pro2Cmd[0] << 8) & 0xFF00;
Si446xCmd.GET_ADC_READING.GPIO_ADC |= (U16)Pro2Cmd[1] & 0x00FF;
Si446xCmd.GET_ADC_READING.BATTERY_ADC = ((U16)Pro2Cmd[2] << 8) & 0xFF00;
Si446xCmd.GET_ADC_READING.BATTERY_ADC |= (U16)Pro2Cmd[3] & 0x00FF;
Si446xCmd.GET_ADC_READING.TEMP_ADC = ((U16)Pro2Cmd[4] << 8) & 0xFF00;
Si446xCmd.GET_ADC_READING.TEMP_ADC |= (U16)Pro2Cmd[5] & 0x00FF;
}
/*!
* Receives information from the radio of the current packet. Optionally can be used to modify
* the Packet Handler properties during packet reception.
*
* @param FIELD_NUMBER_MASK Packet Field number mask value.
* @param LEN Length value.
* @param DIFF_LEN Difference length.
*/
void si446x_get_packet_info(U8 FIELD_NUMBER_MASK, U16 LEN, S16 DIFF_LEN )
{
Pro2Cmd[0] = SI446X_CMD_ID_PACKET_INFO;
Pro2Cmd[1] = FIELD_NUMBER_MASK;
Pro2Cmd[2] = (U8)(LEN >> 8);
Pro2Cmd[3] = (U8)(LEN);
// the different of the byte, althrough it is signed, but to command hander
// it can treat it as unsigned
Pro2Cmd[4] = (U8)((U16)DIFF_LEN >> 8);
Pro2Cmd[5] = (U8)(DIFF_LEN);
radio_comm_SendCmdGetResp( SI446X_CMD_ARG_COUNT_PACKET_INFO,
Pro2Cmd,
SI446X_CMD_REPLY_COUNT_PACKET_INFO,
Pro2Cmd );
Si446xCmd.PACKET_INFO.LENGTH = ((U16)Pro2Cmd[0] << 8) & 0xFF00;
Si446xCmd.PACKET_INFO.LENGTH |= (U16)Pro2Cmd[1] & 0x00FF;
}
/*!
* Gets the Packet Handler status flags. Optionally clears them.
*
* @param PH_CLR_PEND Flags to clear.
*/
void si446x_get_ph_status(U8 PH_CLR_PEND)
{
Pro2Cmd[0] = SI446X_CMD_ID_GET_PH_STATUS;
Pro2Cmd[1] = PH_CLR_PEND;
radio_comm_SendCmdGetResp( SI446X_CMD_ARG_COUNT_GET_PH_STATUS,
Pro2Cmd,
SI446X_CMD_REPLY_COUNT_GET_PH_STATUS,
Pro2Cmd );
Si446xCmd.GET_PH_STATUS.PH_PEND = Pro2Cmd[0];
Si446xCmd.GET_PH_STATUS.PH_STATUS = Pro2Cmd[1];
}
/*!
* Gets the Modem status flags. Optionally clears them.
*
* @param MODEM_CLR_PEND Flags to clear.
*/
void si446x_get_modem_status( U8 MODEM_CLR_PEND )
{
Pro2Cmd[0] = SI446X_CMD_ID_GET_MODEM_STATUS;
Pro2Cmd[1] = MODEM_CLR_PEND;
radio_comm_SendCmdGetResp( SI446X_CMD_ARG_COUNT_GET_MODEM_STATUS,
Pro2Cmd,
SI446X_CMD_REPLY_COUNT_GET_MODEM_STATUS,
Pro2Cmd );
Si446xCmd.GET_MODEM_STATUS.MODEM_PEND = Pro2Cmd[0];
Si446xCmd.GET_MODEM_STATUS.MODEM_STATUS = Pro2Cmd[1];
Si446xCmd.GET_MODEM_STATUS.CURR_RSSI = Pro2Cmd[2];
Si446xCmd.GET_MODEM_STATUS.LATCH_RSSI = Pro2Cmd[3];
Si446xCmd.GET_MODEM_STATUS.ANT1_RSSI = Pro2Cmd[4];
Si446xCmd.GET_MODEM_STATUS.ANT2_RSSI = Pro2Cmd[5];
Si446xCmd.GET_MODEM_STATUS.AFC_FREQ_OFFSET = ((U16)Pro2Cmd[6] << 8) & 0xFF00;
Si446xCmd.GET_MODEM_STATUS.AFC_FREQ_OFFSET |= (U16)Pro2Cmd[7] & 0x00FF;
}
/*!
* Gets the Chip status flags. Optionally clears them.
*
* @param CHIP_CLR_PEND Flags to clear.
*/
void si446x_get_chip_status( U8 CHIP_CLR_PEND )
{
Pro2Cmd[0] = SI446X_CMD_ID_GET_CHIP_STATUS;
Pro2Cmd[1] = CHIP_CLR_PEND;
radio_comm_SendCmdGetResp( SI446X_CMD_ARG_COUNT_GET_CHIP_STATUS,
Pro2Cmd,
SI446X_CMD_REPLY_COUNT_GET_CHIP_STATUS,
Pro2Cmd );
Si446xCmd.GET_CHIP_STATUS.CHIP_PEND = Pro2Cmd[0];
Si446xCmd.GET_CHIP_STATUS.CHIP_STATUS = Pro2Cmd[1];
Si446xCmd.GET_CHIP_STATUS.CMD_ERR_STATUS = Pro2Cmd[2];
}
/*!
* Performs image rejection calibration. Completion can be monitored by polling CTS or waiting for CHIP_READY interrupt source.
*
* @param SEARCHING_STEP_SIZE
* @param SEARCHING_RSSI_AVG
* @param RX_CHAIN_SETTING1
* @param RX_CHAIN_SETTING2
*/
void si446x_ircal(U8 SEARCHING_STEP_SIZE, U8 SEARCHING_RSSI_AVG, U8 RX_CHAIN_SETTING1, U8 RX_CHAIN_SETTING2)
{
Pro2Cmd[0] = SI446X_CMD_ID_IRCAL;
Pro2Cmd[1] = SEARCHING_STEP_SIZE;
Pro2Cmd[2] = SEARCHING_RSSI_AVG;
Pro2Cmd[3] = RX_CHAIN_SETTING1;
Pro2Cmd[4] = RX_CHAIN_SETTING2;
radio_comm_SendCmd( SI446X_CMD_ARG_COUNT_IRCAL, Pro2Cmd);
}
/*!
* Image rejection calibration. Forces a specific value for IR calibration, and reads back calibration values from previous calibrations
*
* @param IRCAL_AMP
* @param IRCAL_PH
*/
void si446x_ircal_manual(U8 IRCAL_AMP, U8 IRCAL_PH)
{
Pro2Cmd[0] = SI446X_CMD_ID_IRCAL_MANUAL;
Pro2Cmd[1] = IRCAL_AMP;
Pro2Cmd[2] = IRCAL_PH;
radio_comm_SendCmdGetResp( SI446X_CMD_ARG_COUNT_IRCAL_MANUAL,
Pro2Cmd,
SI446X_CMD_REPLY_COUNT_IRCAL_MANUAL,
Pro2Cmd );
Si446xCmd.IRCAL_MANUAL.IRCAL_AMP_REPLY = Pro2Cmd[0];
Si446xCmd.IRCAL_MANUAL.IRCAL_PH_REPLY = Pro2Cmd[1];
}
/*!
* Requests the current state of the device and lists pending TX and RX requests
*/
void si446x_request_device_state(void)
{
Pro2Cmd[0] = SI446X_CMD_ID_REQUEST_DEVICE_STATE;
radio_comm_SendCmdGetResp( SI446X_CMD_ARG_COUNT_REQUEST_DEVICE_STATE,
Pro2Cmd,
SI446X_CMD_REPLY_COUNT_REQUEST_DEVICE_STATE,
Pro2Cmd );
Si446xCmd.REQUEST_DEVICE_STATE.CURR_STATE = Pro2Cmd[0];
Si446xCmd.REQUEST_DEVICE_STATE.CURRENT_CHANNEL = Pro2Cmd[1];
}
/*!
* While in TX state this will hop to the frequency specified by the parameters
*
* @param INTE New INTE register value.
* @param FRAC2 New FRAC2 register value.
* @param FRAC1 New FRAC1 register value.
* @param FRAC0 New FRAC0 register value.
* @param VCO_CNT1 New VCO_CNT1 register value.
* @param VCO_CNT0 New VCO_CNT0 register value.
* @param PLL_SETTLE_TIME1 New PLL_SETTLE_TIME1 register value.
* @param PLL_SETTLE_TIME0 New PLL_SETTLE_TIME0 register value.
*/
void si446x_tx_hop(U8 INTE, U8 FRAC2, U8 FRAC1, U8 FRAC0, U8 VCO_CNT1, U8 VCO_CNT0, U8 PLL_SETTLE_TIME1, U8 PLL_SETTLE_TIME0)
{
Pro2Cmd[0] = SI446X_CMD_ID_TX_HOP;
Pro2Cmd[1] = INTE;
Pro2Cmd[2] = FRAC2;
Pro2Cmd[3] = FRAC1;
Pro2Cmd[4] = FRAC0;
Pro2Cmd[5] = VCO_CNT1;
Pro2Cmd[6] = VCO_CNT0;
Pro2Cmd[7] = PLL_SETTLE_TIME1;
Pro2Cmd[8] = PLL_SETTLE_TIME0;
radio_comm_SendCmd( SI446X_CMD_ARG_COUNT_TX_HOP, Pro2Cmd );
}
/*!
* While in RX state this will hop to the frequency specified by the parameters and start searching for a preamble.
*
* @param INTE New INTE register value.
* @param FRAC2 New FRAC2 register value.
* @param FRAC1 New FRAC1 register value.
* @param FRAC0 New FRAC0 register value.
* @param VCO_CNT1 New VCO_CNT1 register value.
* @param VCO_CNT0 New VCO_CNT0 register value.
*/
void si446x_rx_hop(U8 INTE, U8 FRAC2, U8 FRAC1, U8 FRAC0, U8 VCO_CNT1, U8 VCO_CNT0)
{
Pro2Cmd[0] = SI446X_CMD_ID_RX_HOP;
Pro2Cmd[1] = INTE;
Pro2Cmd[2] = FRAC2;
Pro2Cmd[3] = FRAC1;
Pro2Cmd[4] = FRAC0;
Pro2Cmd[5] = VCO_CNT1;
Pro2Cmd[6] = VCO_CNT0;
radio_comm_SendCmd( SI446X_CMD_ARG_COUNT_RX_HOP, Pro2Cmd );
}
/*! Sends START_TX command ID to the radio with no input parameters
*
*/
void si446x_start_tx_fast( void )
{
Pro2Cmd[0] = SI446X_CMD_ID_START_TX;
radio_comm_SendCmd( 1, Pro2Cmd );
}
/*!
* Sends START_RX command ID to the radio with no input parameters
*
*/
void si446x_start_rx_fast( void )
{
Pro2Cmd[0] = SI446X_CMD_ID_START_RX;
radio_comm_SendCmd( 1, Pro2Cmd );
}
/*!
* Clear all Interrupt status/pending flags. Does NOT read back interrupt flags
*
*/
void si446x_get_int_status_fast_clear( void )
{
Pro2Cmd[0] = SI446X_CMD_ID_GET_INT_STATUS;
radio_comm_SendCmd( 1, Pro2Cmd );
}
/*!
* Clear and read all Interrupt status/pending flags
*
*/
void si446x_get_int_status_fast_clear_read(void)
{
Pro2Cmd[0] = SI446X_CMD_ID_GET_INT_STATUS;
radio_comm_SendCmdGetResp( 1,
Pro2Cmd,
SI446X_CMD_REPLY_COUNT_GET_INT_STATUS,
Pro2Cmd );
Si446xCmd.GET_INT_STATUS.INT_PEND = Pro2Cmd[0];
Si446xCmd.GET_INT_STATUS.INT_STATUS = Pro2Cmd[1];
Si446xCmd.GET_INT_STATUS.PH_PEND = Pro2Cmd[2];
Si446xCmd.GET_INT_STATUS.PH_STATUS = Pro2Cmd[3];
Si446xCmd.GET_INT_STATUS.MODEM_PEND = Pro2Cmd[4];
Si446xCmd.GET_INT_STATUS.MODEM_STATUS = Pro2Cmd[5];
Si446xCmd.GET_INT_STATUS.CHIP_PEND = Pro2Cmd[6];
Si446xCmd.GET_INT_STATUS.CHIP_STATUS = Pro2Cmd[7];
}
/*!
* Reads back current GPIO pin configuration. Does NOT configure GPIO pins
*
*/
void si446x_gpio_pin_cfg_fast( void )
{
Pro2Cmd[0] = SI446X_CMD_ID_GPIO_PIN_CFG;
radio_comm_SendCmdGetResp( 1,
Pro2Cmd,
SI446X_CMD_REPLY_COUNT_GPIO_PIN_CFG,
Pro2Cmd );
Si446xCmd.GPIO_PIN_CFG.GPIO[0] = Pro2Cmd[0];
Si446xCmd.GPIO_PIN_CFG.GPIO[1] = Pro2Cmd[1];
Si446xCmd.GPIO_PIN_CFG.GPIO[2] = Pro2Cmd[2];
Si446xCmd.GPIO_PIN_CFG.GPIO[3] = Pro2Cmd[3];
Si446xCmd.GPIO_PIN_CFG.NIRQ = Pro2Cmd[4];
Si446xCmd.GPIO_PIN_CFG.SDO = Pro2Cmd[5];
Si446xCmd.GPIO_PIN_CFG.GEN_CONFIG = Pro2Cmd[6];
}
/*!
* Clear all Packet Handler status flags. Does NOT read back interrupt flags
*
*/
void si446x_get_ph_status_fast_clear( void )
{
Pro2Cmd[0] = SI446X_CMD_ID_GET_PH_STATUS;
Pro2Cmd[1] = 0;
radio_comm_SendCmd( 2, Pro2Cmd );
}
/*!
* Clear and read all Packet Handler status flags.
*
*/
void si446x_get_ph_status_fast_clear_read(void)
{
Pro2Cmd[0] = SI446X_CMD_ID_GET_PH_STATUS;
radio_comm_SendCmdGetResp( 1,
Pro2Cmd,
SI446X_CMD_REPLY_COUNT_GET_PH_STATUS,
Pro2Cmd );
Si446xCmd.GET_PH_STATUS.PH_PEND = Pro2Cmd[0];
Si446xCmd.GET_PH_STATUS.PH_STATUS = Pro2Cmd[1];
}
/*!
* Clear all Modem status flags. Does NOT read back interrupt flags
*
*/
void si446x_get_modem_status_fast_clear( void )
{
Pro2Cmd[0] = SI446X_CMD_ID_GET_MODEM_STATUS;
Pro2Cmd[1] = 0;
radio_comm_SendCmd( 2, Pro2Cmd );
}
/*!
* Clear and read all Modem status flags.
*
*/
void si446x_get_modem_status_fast_clear_read( void )
{
Pro2Cmd[0] = SI446X_CMD_ID_GET_MODEM_STATUS;
radio_comm_SendCmdGetResp( 1,
Pro2Cmd,
SI446X_CMD_REPLY_COUNT_GET_MODEM_STATUS,
Pro2Cmd );
Si446xCmd.GET_MODEM_STATUS.MODEM_PEND = Pro2Cmd[0];
Si446xCmd.GET_MODEM_STATUS.MODEM_STATUS = Pro2Cmd[1];
Si446xCmd.GET_MODEM_STATUS.CURR_RSSI = Pro2Cmd[2];
Si446xCmd.GET_MODEM_STATUS.LATCH_RSSI = Pro2Cmd[3];
Si446xCmd.GET_MODEM_STATUS.ANT1_RSSI = Pro2Cmd[4];
Si446xCmd.GET_MODEM_STATUS.ANT2_RSSI = Pro2Cmd[5];
Si446xCmd.GET_MODEM_STATUS.AFC_FREQ_OFFSET = ((U16)Pro2Cmd[6] << 8) & 0xFF00;
Si446xCmd.GET_MODEM_STATUS.AFC_FREQ_OFFSET |= (U16)Pro2Cmd[7] & 0x00FF;
}
/*!
* Clear all Chip status flags. Does NOT read back interrupt flags
*
*/
void si446x_get_chip_status_fast_clear( void )
{
Pro2Cmd[0] = SI446X_CMD_ID_GET_CHIP_STATUS;
Pro2Cmd[1] = 0;
radio_comm_SendCmd( 2, Pro2Cmd );
}
/*!
* Clear and read all Chip status flags.
*
*/
void si446x_get_chip_status_fast_clear_read( void )
{
Pro2Cmd[0] = SI446X_CMD_ID_GET_CHIP_STATUS;
radio_comm_SendCmdGetResp( 1,
Pro2Cmd,
SI446X_CMD_REPLY_COUNT_GET_CHIP_STATUS,
Pro2Cmd );
Si446xCmd.GET_CHIP_STATUS.CHIP_PEND = Pro2Cmd[0];
Si446xCmd.GET_CHIP_STATUS.CHIP_STATUS = Pro2Cmd[1];
Si446xCmd.GET_CHIP_STATUS.CMD_ERR_STATUS = Pro2Cmd[2];
}
/*!
* Resets the RX/TX FIFO. Does not read back anything from TX/RX FIFO
*
*/
void si446x_fifo_info_fast_reset(U8 FIFO)
{
Pro2Cmd[0] = SI446X_CMD_ID_FIFO_INFO;
Pro2Cmd[1] = FIFO;
radio_comm_SendCmd( 2, Pro2Cmd );
}
/*!
* Reads RX/TX FIFO count space. Does NOT reset RX/TX FIFO
*
*/
void si446x_fifo_info_fast_read(void)
{
Pro2Cmd[0] = SI446X_CMD_ID_FIFO_INFO;
radio_comm_SendCmdGetResp( 1,
Pro2Cmd,
SI446X_CMD_REPLY_COUNT_FIFO_INFO,
Pro2Cmd );
Si446xCmd.FIFO_INFO.RX_FIFO_COUNT = Pro2Cmd[0];
Si446xCmd.FIFO_INFO.TX_FIFO_SPACE = Pro2Cmd[1];
}
#endif /* RADIO_DRIVER_FULL_SUPPORT */
#endif /* RADIO_DRIVER_EXTENDED_SUPPORT */
/*!
* File:
* si446x_api_lib.h
*
* Description:
* This file contains the Si446x API library.
*
* Silicon Laboratories Confidential
* Copyright 2011 Silicon Laboratories, Inc.
*/
#ifndef _SI446X_API_LIB_H_
#define _SI446X_API_LIB_H_
extern SEGMENT_VARIABLE( Si446xCmd, union si446x_cmd_reply_union, SEG_XDATA );
extern SEGMENT_VARIABLE( Pro2Cmd[16], U8, SEG_XDATA );
#define SI466X_FIFO_SIZE 64
enum
{
SI446X_SUCCESS,
SI446X_NO_PATCH,
SI446X_CTS_TIMEOUT,
SI446X_PATCH_FAIL,
SI446X_COMMAND_ERROR
};
/* Minimal driver support functions */
void si446x_reset(void);
void si446x_power_up(U8 BOOT_OPTIONS, U8 XTAL_OPTIONS, U32 XO_FREQ);
U8 si446x_configuration_init(const U8* pSetPropCmd);
U8 si446x_apply_patch(void);
void si446x_part_info(void);
void si446x_start_tx(U8 CHANNEL, U8 CONDITION, U16 TX_LEN);
void si446x_start_rx(U8 CHANNEL, U8 CONDITION, U16 RX_LEN, U8 NEXT_STATE1, U8 NEXT_STATE2, U8 NEXT_STATE3);
void si446x_get_int_status(U8 PH_CLR_PEND, U8 MODEM_CLR_PEND, U8 CHIP_CLR_PEND);
void si446x_gpio_pin_cfg(U8 GPIO0, U8 GPIO1, U8 GPIO2, U8 GPIO3, U8 NIRQ, U8 SDO, U8 GEN_CONFIG);
void si446x_set_property( U8 GROUP, U8 NUM_PROPS, U8 START_PROP, ... );
void si446x_change_state(U8 NEXT_STATE1);
#ifdef RADIO_DRIVER_EXTENDED_SUPPORT
/* Extended driver support functions */
void si446x_nop(void);
void si446x_fifo_info(U8 FIFO);
void si446x_write_tx_fifo( U8 numBytes, U8* pData );
void si446x_read_rx_fifo( U8 numBytes, U8* pRxData );
void si446x_get_property(U8 GROUP, U8 NUM_PROPS, U8 START_PROP);
#ifdef RADIO_DRIVER_FULL_SUPPORT
/* Full driver support functions */
void si446x_func_info(void);
void si446x_frr_a_read(U8 respByteCount);
void si446x_frr_b_read(U8 respByteCount);
void si446x_frr_c_read(U8 respByteCount);
void si446x_frr_d_read(U8 respByteCount);
void si446x_get_adc_reading(U8 ADC_EN);
void si446x_get_packet_info(U8 FIELD_NUMBER_MASK, U16 LEN, S16 DIFF_LEN );
void si446x_get_ph_status(U8 PH_CLR_PEND);
void si446x_get_modem_status( U8 MODEM_CLR_PEND );
void si446x_get_chip_status( U8 CHIP_CLR_PEND );
void si446x_ircal_manual(U8 IRCAL_AMP, U8 IRCAL_PH);
void si446x_protocol_cfg(U8 PROTOCOL);
void si446x_request_device_state(void);
void si446x_tx_hop(U8 INTE, U8 FRAC2, U8 FRAC1, U8 FRAC0, U8 VCO_CNT1, U8 VCO_CNT0, U8 PLL_SETTLE_TIME1, U8 PLL_SETTLE_TIME0);
void si446x_rx_hop(U8 INTE, U8 FRAC2, U8 FRAC1, U8 FRAC0, U8 VCO_CNT1, U8 VCO_CNT0);
void si446x_start_tx_fast( void );
void si446x_start_rx_fast( void );
void si446x_get_int_status_fast_clear( void );
void si446x_get_int_status_fast_clear_read( void );
void si446x_gpio_pin_cfg_fast( void );
void si446x_get_ph_status_fast_clear( void );
void si446x_get_ph_status_fast_clear_read( void );
void si446x_get_modem_status_fast_clear( void );
void si446x_get_modem_status_fast_clear_read( void );
void si446x_get_chip_status_fast_clear( void );
void si446x_get_chip_status_fast_clear_read( void );
void si446x_fifo_info_fast_reset(U8 FIFO);
void si446x_fifo_info_fast_read(void);
#endif
#endif
#endif //_SI446X_API_LIB_H_
This source diff could not be displayed because it is too large. You can view the blob instead.
/*!
* Silicon Laboratories Confidential
* Copyright 2011 Silicon Laboratories, Inc.
*
*/
#ifndef _SI446X_DEFS_H_
#define _SI446X_DEFS_H_
#include "si446x_cmd.h"
#include "si446x_prop.h"
#endif // _SI446X_DEFS_H_
/*
* Silicon Laboratories Confidential
* Copyright 2011 Silicon Laboratories, Inc.
*
* THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT!
*/
#include "..\..\..\bsp.h"
//SEGMENT_VARIABLE( Si446xChipPend, U8, SEG_BDATA );
//SBIT(Si446xWUTPend,Si446xChipPend,0);
//SBIT(Si446xLowBattPend,Si446xChipPend,1);
//SBIT(Si446xChipReadyPend,Si446xChipPend,2);
//SBIT(Si446xCmdErrPend,Si446xChipPend,2);
//SBIT(Si446xStateChangePend,Si446xChipPend,2);
//SBIT(Si446xFifoUnderflowOverflowErrorPend,Si446xChipPend,2);
//SEGMENT_VARIABLE( Si446xPhPend, U8, SEG_BDATA );
//SEGMENT_VARIABLE( Si446xModemPend, U8, SEG_BDATA );
#define Si446xWUTPend Si446xPhPend0
#define Si446xLowBattPend Si446xPhPend1
#define Si446xChipReadyPend Si446xPhPend2
#define Si446xCmdErrPend Si446xPhPend3
#define Si446xStateChangePend Si446xPhPend4
#define Si446xFifoUnderflowOverflowErrorPend Si446xPhPend5
#define Si446xDummyPhPend6 Si446xPhPend6
#define Si446xDummyPhPend7 Si446xPhPend7
#define Si446xSyncDetectPend Si446xModemPend0
#define Si446xPreambleDetectPend Si446xModemPend1
#define Si446xInvalidPreamblePend Si446xModemPend2
#define Si446xRssiPend Si446xModemPend3
#define Si446xRssiJumpPend Si446xModemPend4
#define Si446xInvalidSyncPend Si446xModemPend5
#define Si446xDummyModemPend6 Si446xModemPend6
#define Si446xDummyModemPend7 Si446xModemPend7
#define Si446xRxFifoAlmostFullPend Si446xChipPend0
#define Si446xTxFifoAlmostEmptyPend Si446xChipPend1
#define Si446xCrc16ErrorPend Si446xChipPend2
#define Si446xCrc32ErrorPend Si446xChipPend3
#define Si446xPacketRxPend Si446xChipPend4
#define Si446xPacketSentPend Si446xChipPend5
#define Si446xFilterMissPend Si446xChipPend6
#define Si446xFilterMatchPend Si446xChipPend7
/*!
* Do NOT use SEG_BDATA as that is not understood by SDCC!
* Use BITS, WRITE_TO_BIT_ARRAY and READ_FROM_BIT_ARRAY instead to allocate and
* handle bit arrays in a convenient way.
*
* Allocate all 8bits if WRITE_TO_BIT_ARRAY and READ_FROM_BIT_ARRAY macros
* are to be used. Otherwise these macros would read/write bits that are
* placed within that byte by the linker.
*/
BITS(Si446xPhPend, 0);
BITS(Si446xPhPend, 1);
BITS(Si446xPhPend, 2);
BITS(Si446xPhPend, 3);
BITS(Si446xPhPend, 4);
BITS(Si446xPhPend, 5);
BITS(Si446xPhPend, 6);
BITS(Si446xPhPend, 7);
BITS(Si446xModemPend, 0);
BITS(Si446xModemPend, 1);
BITS(Si446xModemPend, 2);
BITS(Si446xModemPend, 3);
BITS(Si446xModemPend, 4);
BITS(Si446xModemPend, 5);
BITS(Si446xModemPend, 6);
BITS(Si446xModemPend, 7);
BITS(Si446xChipPend, 0);
BITS(Si446xChipPend, 1);
BITS(Si446xChipPend, 2);
BITS(Si446xChipPend, 3);
BITS(Si446xChipPend, 4);
BITS(Si446xChipPend, 5);
BITS(Si446xChipPend, 6);
BITS(Si446xChipPend, 7);
/*!
* This function is used to handle the assertion of nIRQ of the si446x chip.
*
* @note This function can take up to 6 ms depending on the startup time of the
* si446x chip.
*
*/
void si446x_nirq_process(void)
{
#ifdef SI446X_USER_CONFIG_USE_FRR_ABC_FOR_NIRQ
SEGMENT_VARIABLE(pendBits[3], U8, SEG_DATA);
si446x_frr_read();
#else
si446x_get_int_status(0, 0, 0);
// Si446xPhPend = Si446xCmd.GET_INT_STATUS.PH_PEND;
// Si446xModemPend = Si446xCmd.GET_INT_STATUS.MODEM_PEND;
// Si446xChipPend = Si446xCmd.GET_INT_STATUS.CHIP_PEND;
WRITE_TO_BIT_ARRAY(Si446xPhPend, Si446xCmd.GET_INT_STATUS.PH_PEND);
WRITE_TO_BIT_ARRAY(Si446xModemPend, Si446xCmd.GET_INT_STATUS.MODEM_PEND);
WRITE_TO_BIT_ARRAY(Si446xChipPend, Si446xCmd.GET_INT_STATUS.CHIP_PEND);
#endif
}
/*!
* Silicon Laboratories Confidential
* Copyright 2011 Silicon Laboratories, Inc.
*
* Public API for the Si446x nIRQ interface.
*/
#ifndef _SI446X_NIRQ_H
#define _SI446X_NIRQ_H
/* ======================================= *
* I N C L U D E *
* ======================================= */
/* ======================================= *
* D E F I N I T I O N S *
* ======================================= */
/* ======================================= *
* G L O B A L V A R I A B L E S *
* ======================================= */
/* ======================================= *
* F U N C T I O N P R O T O T Y P E S *
* ======================================= */
#endif //_SI446X_NIRQ_H
// COPYRIGHT=2013 Silicon Laboratories, Inc.
// GENERATED=15:46 January 24 2013
// ROMID=0x03
// PATCHID=0xF692
// REQUIRES=NONE
// SIZE=2128
// FUNCTION=MAIN
// MAJOR=3
// MINOR=0
// BUILD=27
// CRCT=0xF776
#define SI446X_PATCH_ROMID 03
#define SI446X_PATCH_ID 27
#define SI446X_PATCH_CMDS \
{ 0x04,0x11,0xF7,0x76,0x00,0x00,0xA6,0x82 }, \
{ 0x05,0x61,0xE6,0x82,0x5E,0xB7,0xFB,0x93 }, \
{ 0x05,0x1E,0x12,0xBD,0x5A,0xC2,0x52,0x41 }, \
{ 0xE7,0xF4,0xDF,0x6A,0x24,0xD9,0xBA,0x31 }, \
{ 0xEF,0x00,0x1C,0xDA,0xA2,0x5C,0xB3,0x00 }, \
{ 0xE7,0x4E,0x93,0xE3,0xFE,0x4C,0xAC,0x43 }, \
{ 0xEF,0xA3,0xCD,0x10,0x30,0xD8,0x9B,0x0F }, \
{ 0xEF,0x5B,0x09,0x3A,0x58,0x74,0x70,0xA9 }, \
{ 0xEF,0xBC,0x8B,0xDC,0x26,0xA2,0xE8,0xB7 }, \
{ 0xEF,0x67,0x5A,0xEE,0xA4,0x47,0x20,0x30 }, \
{ 0xEF,0x20,0x2D,0xE3,0xB0,0x51,0x39,0x9C }, \
{ 0xEF,0x6B,0x22,0x1C,0x6E,0x4E,0xC8,0xC4 }, \
{ 0xE7,0x1B,0xCD,0xDF,0x46,0xF1,0x30,0x4D }, \
{ 0xE7,0x7B,0x7C,0xCE,0x8D,0xDA,0x9B,0x1F }, \
{ 0xEF,0x8C,0xFA,0xCD,0xD5,0x67,0xE7,0x19 }, \
{ 0xE7,0x27,0x50,0xD2,0xBF,0xEE,0xAB,0xBA }, \
{ 0xEF,0x66,0xE7,0x15,0x1E,0xAE,0x86,0x13 }, \
{ 0xEF,0x38,0xA8,0x6C,0x15,0x22,0xCD,0x4A }, \
{ 0xE7,0x6A,0x1F,0x1D,0xE8,0x7C,0xEA,0x70 }, \
{ 0xE7,0xFB,0x6D,0x41,0xC7,0x5F,0xC8,0x92 }, \
{ 0xEF,0x87,0xE0,0x1D,0x3C,0x4F,0x60,0x71 }, \
{ 0xE7,0xF9,0x26,0xF4,0x3C,0x48,0x94,0x38 }, \
{ 0xE7,0x44,0x37,0x87,0x6A,0x09,0xE7,0x01 }, \
{ 0xEF,0x44,0x81,0x1C,0x05,0x45,0x95,0x4D }, \
{ 0xEF,0xB8,0x7B,0xFF,0xAE,0xFC,0x01,0xE9 }, \
{ 0xE7,0x08,0xDA,0x82,0x5C,0x0A,0xD8,0x5C }, \
{ 0xE7,0x3F,0x4C,0x51,0x1D,0x2A,0xE4,0x58 }, \
{ 0xEF,0x9A,0x81,0x10,0x7C,0x9F,0x03,0x32 }, \
{ 0xE7,0x98,0x48,0xCE,0x8D,0x9F,0x57,0x24 }, \
{ 0xEF,0x05,0x38,0xCC,0x72,0xAC,0xE1,0x99 }, \
{ 0xE7,0x87,0x63,0x4D,0x6C,0x89,0x6D,0xC6 }, \
{ 0xE7,0x05,0xDF,0x38,0x93,0xDD,0xBB,0xB9 }, \
{ 0xEF,0x5F,0x54,0x44,0x6D,0x05,0x0E,0x18 }, \
{ 0xE7,0xD3,0x5D,0x95,0x95,0x2E,0xA1,0xD8 }, \
{ 0xE7,0x71,0x18,0x02,0x5D,0xEE,0x6A,0x39 }, \
{ 0xEF,0xED,0x5A,0x57,0x03,0x14,0x8D,0xF6 }, \
{ 0xE7,0x91,0xCB,0xCB,0xC5,0xD5,0x36,0xFA }, \
{ 0xEF,0xD1,0x05,0x08,0xA2,0x20,0xC5,0xB4 }, \
{ 0xEF,0x2B,0xE4,0xD9,0xD3,0xF0,0x08,0x81 }, \
{ 0xE2,0xA4,0xC4,0xAE,0x7D,0xFE,0xFD,0xB0 }, \
{ 0x05,0x2B,0xD9,0xEE,0x9F,0xF0,0xC1,0xCC }, \
{ 0xEF,0xD1,0xD9,0x6B,0x80,0x82,0x16,0xF0 }, \
{ 0xE7,0x48,0xBA,0xD0,0x20,0xC7,0x80,0x2E }, \
{ 0xE7,0xFE,0xC7,0x59,0xC1,0xDA,0x45,0x29 }, \
{ 0xEF,0x83,0x3F,0xE9,0xD2,0x55,0x90,0xAE }, \
{ 0xEF,0x7C,0xEB,0x86,0x5C,0x74,0x4C,0x2C }, \
{ 0xE7,0x92,0x78,0x05,0xF1,0x5D,0x85,0x76 }, \
{ 0xEF,0x70,0xC5,0x39,0x54,0x01,0x97,0xCB }, \
{ 0xEF,0xBF,0x89,0xDB,0x23,0x3A,0x29,0x25 }, \
{ 0xEF,0x1B,0x50,0x0A,0x0C,0x0A,0x95,0x13 }, \
{ 0xEF,0x8F,0x30,0xBF,0x7A,0xB5,0x0F,0x48 }, \
{ 0xEF,0xE1,0x08,0xAB,0xB5,0x2E,0x44,0x96 }, \
{ 0xE7,0x47,0xBB,0xAD,0xBD,0x3F,0x3D,0x7B }, \
{ 0xEF,0xE7,0x06,0xFF,0xF1,0xCA,0xB7,0x50 }, \
{ 0xEF,0xB9,0x10,0xFA,0x01,0x5A,0x03,0x7C }, \
{ 0xE7,0xA8,0x1C,0x82,0x8F,0x57,0xCF,0xC3 }, \
{ 0xE7,0xEE,0xE1,0xDE,0xEF,0x29,0xA8,0x77 }, \
{ 0xEF,0x01,0xCF,0xAD,0x0F,0xA2,0x1C,0xC8 }, \
{ 0xEF,0x13,0x7D,0x0F,0xDE,0xBD,0xC2,0xE1 }, \
{ 0xEF,0xA7,0xEF,0x51,0x95,0xAE,0x50,0x31 }, \
{ 0xEF,0xC3,0xC7,0x25,0xC7,0xAA,0x90,0x18 }, \
{ 0xEF,0xE0,0xD6,0x5C,0xE8,0x78,0xB9,0x34 }, \
{ 0xE7,0xB3,0xE8,0xC8,0xD4,0x07,0x71,0x8F }, \
{ 0xE7,0x58,0x4B,0x0D,0x62,0x3C,0x28,0xCE }, \
{ 0xE7,0xDB,0xE5,0xFC,0x56,0x1C,0xB9,0xFB }, \
{ 0xEF,0x24,0x80,0xC3,0xF2,0xCA,0x5F,0xD5 }, \
{ 0xE7,0x28,0x01,0x4F,0x7B,0x04,0xF6,0x74 }, \
{ 0xEF,0x99,0x2B,0x40,0x63,0xC2,0x13,0x3A }, \
{ 0xE7,0x84,0xB3,0x72,0x8C,0x12,0xF2,0xFB }, \
{ 0xEF,0x53,0xAE,0x3C,0x6B,0xA5,0x85,0x6F }, \
{ 0xE7,0xBF,0x92,0xC3,0xF2,0xC1,0x28,0x43 }, \
{ 0xE7,0x6F,0x6D,0xB1,0x28,0x66,0xEF,0xA0 }, \
{ 0xEF,0xCB,0x51,0x59,0xBC,0x71,0xEE,0xCF }, \
{ 0xE7,0x4F,0x44,0xB3,0xDD,0x7B,0x83,0xBB }, \
{ 0xE7,0x53,0xA1,0x25,0x83,0x8C,0x4B,0x15 }, \
{ 0xE7,0x2D,0x2D,0x58,0x78,0x8E,0x78,0x87 }, \
{ 0xE7,0x6A,0x08,0xFA,0x59,0xE2,0xE4,0x1F }, \
{ 0xEA,0xF9,0x9F,0x7B,0x33,0x03,0x3B,0x8C }, \
{ 0x05,0x93,0xBF,0x74,0xEB,0x86,0x54,0x5C }, \
{ 0xE7,0x16,0xFC,0x76,0xAB,0xFE,0x00,0xAD }, \
{ 0xEF,0x63,0xD5,0x57,0x7E,0xF9,0x87,0x24 }, \
{ 0xEF,0xF9,0x15,0x98,0x52,0xB1,0xFE,0x13 }, \
{ 0xE7,0x06,0x4A,0x6B,0xD7,0x43,0x27,0xD0 }, \
{ 0xE7,0xD1,0x19,0x14,0xCC,0xC2,0x9C,0x8D }, \
{ 0xEF,0x6C,0x3F,0xDE,0x92,0x2A,0x70,0x51 }, \
{ 0xE7,0x3C,0x4F,0xF0,0x2D,0xCC,0x16,0xBE }, \
{ 0xE7,0x50,0xD3,0x5D,0xA4,0x5C,0x13,0x14 }, \
{ 0xE7,0xE1,0xD5,0x8B,0x0C,0x1C,0xEB,0xB9 }, \
{ 0xEF,0x22,0xC3,0xDA,0x99,0xB0,0x35,0x6F }, \
{ 0xE7,0x5D,0x52,0xE7,0xBA,0x89,0x7C,0x08 }, \
{ 0xE7,0x6E,0x76,0xF9,0xDF,0xEC,0xFF,0x8A }, \
{ 0xEF,0xEF,0x55,0x20,0xBF,0x38,0xC6,0x55 }, \
{ 0xEF,0x96,0x07,0x9B,0xBF,0xB9,0x71,0xB0 }, \
{ 0xE7,0xB3,0x23,0x6C,0x75,0x9C,0x20,0x66 }, \
{ 0xE7,0xF1,0x05,0x69,0x7B,0xC4,0x02,0xB7 }, \
{ 0xEF,0x0D,0x38,0xDB,0xD5,0xAE,0x12,0x92 }, \
{ 0xE7,0xFC,0x01,0xCD,0x84,0x83,0xB6,0xCF }, \
{ 0xEF,0xAE,0x4A,0x93,0x78,0xD7,0x41,0x88 }, \
{ 0xEF,0x2E,0x19,0x25,0x40,0x0A,0x1F,0x00 }, \
{ 0xE7,0xD1,0x6C,0x0D,0x1F,0x4F,0x27,0x69 }, \
{ 0xEF,0x7F,0x16,0x03,0xC0,0xF7,0x79,0x14 }, \
{ 0xEF,0x39,0x15,0xF8,0xA1,0x40,0xEE,0xF1 }, \
{ 0xE7,0x34,0x3F,0xE2,0xBF,0x4A,0x77,0xDC }, \
{ 0xE7,0xE6,0xC1,0xEB,0x77,0xA3,0x30,0x9A }, \
{ 0xE7,0x06,0x83,0xEC,0x7D,0xA6,0xBA,0x8B }, \
{ 0xEF,0x10,0xEF,0x4B,0x6B,0x68,0x91,0xA4 }, \
{ 0xEF,0xAC,0x64,0xE3,0xF6,0xB3,0xE4,0x1B }, \
{ 0xEF,0x4F,0x27,0xC0,0xBC,0xE9,0xF4,0xBF }, \
{ 0xEF,0xC3,0xB3,0x4D,0x18,0xE2,0x72,0x35 }, \
{ 0xEF,0x1E,0xFA,0x2E,0x4A,0x99,0x05,0x0A }, \
{ 0xEF,0x41,0x1E,0xEF,0x2F,0x34,0x21,0xE8 }, \
{ 0xEF,0xC1,0xC3,0x58,0x2C,0xF2,0x44,0xD7 }, \
{ 0xEF,0xBB,0xB9,0xB0,0xBA,0xF0,0x94,0x14 }, \
{ 0xEF,0x42,0x90,0xBB,0x6D,0x18,0x65,0xDB }, \
{ 0xEF,0x43,0x85,0x50,0xCF,0xA1,0xB8,0xAE }, \
{ 0xE2,0xC5,0xC8,0xD2,0x67,0x59,0x55,0x1D }, \
{ 0x05,0xA8,0xE6,0x45,0xE9,0x87,0xA7,0x36 }, \
{ 0xEF,0xD3,0x8E,0xC6,0x43,0x2B,0xD3,0x91 }, \
{ 0xEF,0x5E,0x9C,0xBE,0x72,0xC2,0x7E,0xD0 }, \
{ 0xEF,0x4B,0xF6,0xE8,0x11,0xEB,0xA7,0x0C }, \
{ 0xEF,0x55,0x82,0xFF,0x9A,0xA3,0x29,0xE6 }, \
{ 0xE7,0x27,0x6C,0x42,0x7F,0x6C,0x4D,0xBA }, \
{ 0xE7,0x95,0xC5,0xE4,0x0F,0x97,0xA3,0x7D }, \
{ 0xE7,0x53,0xF1,0x3D,0x85,0xA5,0x88,0xBC }, \
{ 0xEF,0xC0,0xE4,0x29,0x84,0x6B,0xEB,0xE5 }, \
{ 0xEF,0x0A,0xAE,0x96,0xC2,0x9F,0xDF,0xE0 }, \
{ 0xE7,0xB5,0x3F,0x29,0x91,0x44,0xB6,0xA7 }, \
{ 0xE7,0x72,0x99,0xB2,0xF7,0x7C,0x00,0x59 }, \
{ 0xE5,0xA7,0xD6,0x24,0xBD,0x25,0x2C,0x7E }, \
{ 0x06,0xD6,0x1D,0xC1,0x8C,0x1C,0x00,0x09 }, \
{ 0x05,0xEF,0xB4,0x86,0x6B,0xAA,0xE9,0x29 }, \
{ 0xE7,0xAD,0xF1,0x17,0xE9,0x4B,0x54,0x23 }, \
{ 0xE5,0x51,0x0C,0x9D,0xD9,0xEF,0x13,0x51 }, \
{ 0x0A,0x8E,0xE1,0x2A,0x83,0xE1,0x38,0x05 }, \
{ 0x05,0xEC,0xE9,0x50,0x42,0x4B,0xD8,0x4A }, \
{ 0xE7,0xA6,0x28,0xD7,0x6A,0x5F,0x3C,0xF4 }, \
{ 0xE7,0x5E,0x2C,0x2F,0xC2,0xAA,0x83,0x84 }, \
{ 0xE7,0x6A,0x88,0xB0,0xAF,0x1E,0xC6,0x21 }, \
{ 0xEF,0xA2,0x28,0x85,0x89,0x3D,0xC4,0x1C }, \
{ 0xEF,0x40,0xE0,0xE7,0xA2,0x6A,0x43,0x2E }, \
{ 0xE7,0x61,0x38,0xFB,0xC6,0xAC,0x2C,0x89 }, \
{ 0xEF,0xAA,0xDD,0x73,0x4C,0x01,0x39,0xFB }, \
{ 0xEF,0x3F,0xF0,0x6F,0x37,0xA9,0x8C,0x4E }, \
{ 0xEF,0xC7,0x49,0x68,0x72,0x1E,0x61,0x23 }, \
{ 0xE7,0xAF,0xF2,0x33,0xBB,0xEB,0x49,0xDE }, \
{ 0xEF,0xEC,0x4D,0x8C,0xDA,0xB1,0x8A,0x0B }, \
{ 0xEF,0x60,0xFA,0x14,0x23,0x7C,0xB9,0x9C }, \
{ 0xE7,0x71,0xDA,0x01,0x45,0x18,0xE8,0x2C }, \
{ 0xEF,0x9F,0xD3,0xB0,0x20,0xDC,0x3D,0x9A }, \
{ 0xEF,0x05,0x5F,0x29,0x30,0x8B,0x4B,0xB2 }, \
{ 0xEF,0xA5,0xCF,0xCB,0x10,0x8A,0x42,0x81 }, \
{ 0xE7,0xA1,0xFF,0xF6,0xBB,0x4F,0x99,0x99 }, \
{ 0xEF,0x93,0xC3,0xFC,0x0D,0xCD,0x0D,0xD8 }, \
{ 0xEF,0x9B,0x02,0x3C,0x08,0xB6,0xDC,0xF3 }, \
{ 0xE7,0xBF,0x46,0xB0,0xDF,0x76,0x35,0x68 }, \
{ 0xE7,0xCE,0xB3,0x3F,0xFE,0xDF,0x9B,0x86 }, \
{ 0xEF,0xD3,0x3A,0x8C,0xC8,0xB2,0xE4,0x04 }, \
{ 0xEF,0xD0,0xFC,0xC0,0xE9,0x9D,0x75,0x32 }, \
{ 0xE7,0x87,0xDC,0x0C,0xFE,0xFA,0x5B,0x0D }, \
{ 0xE7,0x07,0x40,0xCE,0x3C,0x74,0x3A,0xC9 }, \
{ 0xE7,0x4B,0xA3,0x39,0xB2,0xB3,0x69,0xFA }, \
{ 0xEF,0x1C,0xDC,0xAF,0xDC,0xED,0x10,0x34 }, \
{ 0xEF,0x6E,0x0B,0xDE,0x98,0xF9,0x07,0x7A }, \
{ 0xEF,0x23,0x64,0xEA,0x0A,0xFD,0x25,0x0C }, \
{ 0xE7,0x0F,0xDB,0xE6,0xA5,0x91,0x4E,0x5A }, \
{ 0xE7,0x07,0x9B,0x85,0x4E,0xEC,0xAE,0x4F }, \
{ 0xEF,0x1F,0x1C,0x2B,0x13,0xEC,0xCA,0xC2 }, \
{ 0xEF,0xCD,0x97,0xE5,0xC4,0x80,0xB4,0x26 }, \
{ 0xEF,0x03,0x7A,0xAC,0x3F,0xA3,0xB0,0xBB }, \
{ 0xEF,0x06,0x98,0xF3,0xAD,0xDD,0xEC,0xC2 }, \
{ 0xE7,0x5A,0xBE,0x58,0x0E,0x1E,0xD2,0x2D }, \
{ 0xEA,0x4E,0xD8,0xA0,0x05,0xE4,0x19,0x26 }, \
{ 0x05,0x9B,0x9A,0x86,0x90,0x23,0x1E,0xC3 }, \
{ 0xE7,0x2F,0x3A,0x23,0xAE,0x6B,0x44,0x59 }, \
{ 0xEF,0x23,0xA5,0x57,0x39,0x40,0xB3,0xD9 }, \
{ 0xE7,0x53,0x9A,0x57,0x4A,0xF8,0x7B,0x70 }, \
{ 0xEF,0x3C,0xD2,0x39,0x33,0xFC,0xE9,0x5F }, \
{ 0xE7,0xA9,0xA7,0xF0,0x90,0x35,0x54,0x9F }, \
{ 0xE7,0x2A,0x71,0xC2,0xB7,0xCF,0xC1,0xF5 }, \
{ 0xE7,0x93,0x84,0x86,0xFA,0xF4,0x66,0x52 }, \
{ 0xE7,0x14,0x3E,0x9A,0xAC,0xE8,0x66,0x74 }, \
{ 0xEF,0xE2,0xD1,0x9E,0x5D,0x70,0x67,0xCC }, \
{ 0xE7,0x6B,0xB0,0x0A,0xCC,0xC7,0x92,0x75 }, \
{ 0xE7,0x4E,0xD6,0x23,0x4B,0xAA,0xC2,0x1D }, \
{ 0xEF,0x45,0x72,0x8D,0x07,0xC0,0xBC,0x89 }, \
{ 0xE7,0xC0,0x49,0x2D,0xC9,0x05,0xE6,0xC2 }, \
{ 0xEF,0x76,0x8A,0x7C,0x30,0x41,0xFD,0xB0 }, \
{ 0xE7,0x75,0xFA,0xAB,0x73,0xE4,0x4B,0xB5 }, \
{ 0xE7,0xA0,0xBD,0xD7,0x2D,0x4D,0xDF,0x14 }, \
{ 0xEF,0xD4,0xEF,0x1C,0x54,0x4C,0x31,0x0F }, \
{ 0xEF,0xE0,0x64,0xBE,0xBF,0xB4,0x13,0xE6 }, \
{ 0xE7,0x67,0x1B,0x5F,0x14,0xFD,0x39,0x7A }, \
{ 0xEF,0xCA,0xCC,0x92,0x0E,0x0C,0x3A,0x86 }, \
{ 0xEF,0xEF,0x79,0x46,0x5B,0xD7,0x10,0xC5 }, \
{ 0xEF,0xBD,0x04,0x0C,0x38,0x8D,0x1A,0x59 }, \
{ 0xEF,0xA0,0x54,0x94,0xB8,0x47,0x06,0x3B }, \
{ 0xEF,0x05,0x21,0xED,0x54,0xF2,0xEB,0x2E }, \
{ 0xE7,0xCA,0x8F,0x6C,0xA2,0x79,0x86,0x4E }, \
{ 0xEF,0x55,0x20,0x28,0xB5,0x70,0x96,0x62 }, \
{ 0xEF,0xC8,0xD5,0x0F,0x92,0xE3,0x89,0x8A }, \
{ 0xE7,0x96,0x68,0xE0,0xF6,0x18,0xD3,0x3B }, \
{ 0xEF,0x1F,0x8C,0xF9,0x38,0x31,0xD5,0x87 }, \
{ 0xE7,0x64,0x5C,0x1A,0x84,0x73,0x1A,0xD5 }, \
{ 0xEF,0x90,0xEF,0xD2,0x1B,0xE6,0x9E,0x78 }, \
{ 0xEF,0xFD,0xF1,0x52,0x3A,0xA0,0xFD,0xED }, \
{ 0xE7,0x12,0xCC,0x31,0x31,0x9F,0x62,0xBA }, \
{ 0xE7,0x41,0xFC,0xD3,0xC1,0xDE,0x30,0x66 }, \
{ 0xEB,0x98,0x7F,0x02,0xA7,0x88,0xF4,0x44 }, \
{ 0x0A,0x1D,0xF4,0x19,0xE8,0x79,0xD8,0xAF }, \
{ 0x05,0x21,0x28,0x4A,0xB8,0x3A,0x52,0x93 }, \
{ 0xE7,0x03,0x9E,0x28,0x99,0x6A,0xBF,0x64 }, \
{ 0xEF,0x9E,0xA2,0x2D,0xEF,0x6A,0x0D,0x7D }, \
{ 0xEF,0x0B,0xC4,0x44,0xF9,0xA2,0xF5,0x0D }, \
{ 0xE7,0x3B,0x21,0x00,0xC3,0xF7,0x53,0xFC }, \
{ 0xE7,0x28,0x1F,0xC5,0xAD,0x89,0x0C,0xC6 }, \
{ 0xE7,0x42,0xE3,0xC2,0x70,0x47,0xC7,0x7C }, \
{ 0xEF,0x8C,0x67,0x6F,0x53,0xDD,0xE3,0x8C }, \
{ 0xE7,0xFE,0x42,0xA7,0x96,0x22,0x20,0x9A }, \
{ 0xED,0x5A,0xDF,0xA7,0x79,0x3F,0x12,0xBE }, \
{ 0x05,0xD4,0xC2,0x36,0x4F,0x1D,0xA5,0xB9 }, \
{ 0x05,0x64,0x4F,0xC8,0xB9,0x9D,0x5D,0x76 }, \
{ 0xEF,0x3E,0x48,0x87,0x42,0x9B,0x34,0xE0 }, \
{ 0xE7,0x27,0xA4,0x57,0x9B,0x1B,0x13,0x9B }, \
{ 0xE7,0x5E,0x1E,0xE5,0xE9,0x27,0x25,0x71 }, \
{ 0xEF,0x63,0xA3,0x45,0x35,0x50,0xFF,0xCE }, \
{ 0xE7,0x1F,0xEA,0x6C,0x00,0xC8,0xE6,0x9C }, \
{ 0xE7,0x63,0x51,0x4B,0x67,0xB8,0xF0,0xD9 }, \
{ 0xE7,0xEA,0x8F,0x5B,0xC9,0x5F,0x47,0xB2 }, \
{ 0xE7,0x37,0xB5,0x0C,0x57,0xB3,0x85,0x4A }, \
{ 0xEF,0x97,0xC6,0x69,0xA8,0xCC,0xC0,0xCF }, \
{ 0xEF,0x2F,0x39,0x8D,0xE3,0x81,0x91,0x1B }, \
{ 0xE7,0xE2,0x18,0xE2,0x2D,0x6B,0x8E,0x78 }, \
{ 0xEF,0x19,0x24,0x52,0xC7,0xE6,0x54,0x2E }, \
{ 0xE7,0xB9,0xA2,0x11,0xA2,0x28,0x46,0xC6 }, \
{ 0xEF,0x04,0xC8,0xF7,0x04,0xFA,0x3E,0xB7 }, \
{ 0xEF,0x53,0xB9,0x89,0x49,0x26,0x59,0xE5 }, \
{ 0xE7,0xE9,0xFD,0xAB,0xC2,0x46,0x60,0x47 }, \
{ 0xE7,0xD1,0x3D,0xFC,0x74,0x26,0x5F,0xAB }, \
{ 0xE7,0x4F,0x70,0xC6,0xD1,0x82,0x98,0x4B }, \
{ 0xEF,0xC1,0xB8,0xB0,0xD9,0x84,0x5B,0x6F }, \
{ 0xE7,0x7A,0x86,0xCB,0x3C,0x73,0xD2,0x9C }, \
{ 0xE7,0x15,0x9B,0xD9,0x5B,0x07,0x3A,0x28 }, \
{ 0xE7,0x28,0xDE,0x88,0x6C,0x4C,0x9F,0x7A }, \
{ 0xEF,0xC5,0xC6,0x70,0x48,0x40,0x8A,0x88 }, \
{ 0xE7,0x3D,0x32,0x32,0x36,0xE9,0xAF,0x3A }, \
{ 0xEF,0xE4,0x68,0x25,0x20,0xC5,0xAC,0xDB }, \
{ 0xE1,0x2B,0x99,0x1C,0xB2,0x7C,0x77,0x29 }, \
{ 0x05,0x91,0x8B,0x94,0xE8,0x6A,0xB7,0x48 }, \
{ 0x05,0x40,0xE5,0x7A,0x4A,0xBE,0xAC,0x20 }, \
{ 0xE7,0x03,0x54,0x07,0xE5,0x8C,0xC7,0x69 }, \
{ 0xE5,0x40,0x66,0x72,0x5D,0xB2,0x0B,0x9F }, \
{ 0x05,0x63,0xA0,0xB3,0x0C,0x7E,0xE2,0xCD }, \
{ 0x05,0xE7,0x9F,0x8B,0x77,0x42,0xDE,0x20 }, \
{ 0xE7,0xC6,0x59,0xBD,0x07,0x96,0xF7,0xBC }, \
{ 0xEF,0xAB,0x17,0x2B,0x46,0x23,0xD7,0x47 }, \
{ 0xEF,0xC9,0x3E,0x9F,0xA3,0xB9,0x46,0x19 }, \
{ 0xE7,0xA2,0xCA,0xA6,0xCD,0xD3,0x02,0x63 }, \
{ 0xEF,0xA3,0xEF,0x6F,0x81,0x2F,0x84,0xED }, \
{ 0xE1,0x32,0xB9,0xF2,0x1A,0x75,0xA3,0xDB }, \
{ 0x05,0x2A,0xE6,0xD7,0x7C,0x41,0xD6,0x6F }, \
{ 0x05,0x5A,0x36,0x18,0x58,0xA6,0xBD,0x8E }, \
{ 0xEF,0xA1,0xC3,0xCD,0x67,0x96,0x57,0x9F }, \
{ 0xEF,0x7D,0x0D,0xB5,0xCF,0x00,0xC5,0x75 }, \
{ 0xE3,0xC6,0x0E,0x0B,0x10,0x44,0x10,0xEE }, \
{ 0x05,0x12,0x86,0x0D,0xC0,0xA5,0xF6,0x92 }, \
This source diff could not be displayed because it is too large. You can view the blob instead.
/*!
* File:
* radio_comm.h
*
* Description:
* This file contains the RADIO communication layer.
*
* Silicon Laboratories Confidential
* Copyright 2012 Silicon Laboratories, Inc.
*/
/* ======================================= *
* I N C L U D E *
* ======================================= */
#include "..\..\bsp.h"
/* ======================================= *
* D E F I N I T I O N S *
* ======================================= */
/* ======================================= *
* G L O B A L V A R I A B L E S *
* ======================================= */
#if (defined SILABS_RADIO_SI446X) || (defined SILABS_RADIO_SI4455)
BIT ctsWentHigh = 0;
#endif
/* ======================================= *
* L O C A L F U N C T I O N S *
* ======================================= */
/* ======================================= *
* P U B L I C F U N C T I O N S *
* ======================================= */
#if (defined SILABS_RADIO_SI446X) || (defined SILABS_RADIO_SI4455)
/*!
* Gets a command response from the radio chip
*
* @param byteCount Number of bytes to get from the radio chip
* @param pData Pointer to where to put the data
*
* @return CTS value
*/
U8 radio_comm_GetResp(U8 byteCount, U8* pData)
{
SEGMENT_VARIABLE(ctsVal = 0u, U8, SEG_DATA);
SEGMENT_VARIABLE(errCnt = RADIO_CTS_TIMEOUT, U16, SEG_DATA);
while (errCnt != 0) //wait until radio IC is ready with the data
{
radio_hal_ClearNsel();
radio_hal_SpiWriteByte(0x44); //read CMD buffer
ctsVal = radio_hal_SpiReadByte();
if (ctsVal == 0xFF)
{
if (byteCount)
{
radio_hal_SpiReadData(byteCount, pData);
}
radio_hal_SetNsel();
break;
}
radio_hal_SetNsel();
errCnt--;
}
if (errCnt == 0)
{
while(1)
{
/* ERROR!!!! CTS should never take this long. */
#ifdef RADIO_COMM_ERROR_CALLBACK
RADIO_COMM_ERROR_CALLBACK();
#endif
}
}
if (ctsVal == 0xFF)
{
ctsWentHigh = 1;
}
return ctsVal;
}
/*!
* Sends a command to the radio chip
*
* @param byteCount Number of bytes in the command to send to the radio device
* @param pData Pointer to the command to send.
*/
void radio_comm_SendCmd(U8 byteCount, U8* pData)
{
while (!ctsWentHigh)
{
radio_comm_PollCTS();
}
radio_hal_ClearNsel();
radio_hal_SpiWriteData(byteCount, pData);
radio_hal_SetNsel();
ctsWentHigh = 0;
}
/*!
* Gets a command response from the radio chip
*
* @param cmd Command ID
* @param pollCts Set to poll CTS
* @param byteCount Number of bytes to get from the radio chip.
* @param pData Pointer to where to put the data.
*/
void radio_comm_ReadData(U8 cmd, BIT pollCts, U8 byteCount, U8* pData)
{
if(pollCts)
{
while(!ctsWentHigh)
{
radio_comm_PollCTS();
}
}
radio_hal_ClearNsel();
radio_hal_SpiWriteByte(cmd);
radio_hal_SpiReadData(byteCount, pData);
radio_hal_SetNsel();
ctsWentHigh = 0;
}
/*!
* Gets a command response from the radio chip
*
* @param cmd Command ID
* @param pollCts Set to poll CTS
* @param byteCount Number of bytes to get from the radio chip
* @param pData Pointer to where to put the data
*/
void radio_comm_WriteData(U8 cmd, BIT pollCts, U8 byteCount, U8* pData)
{
if(pollCts)
{
while(!ctsWentHigh)
{
radio_comm_PollCTS();
}
}
radio_hal_ClearNsel();
radio_hal_SpiWriteByte(cmd);
radio_hal_SpiWriteData(byteCount, pData);
radio_hal_SetNsel();
ctsWentHigh = 0;
}
/*!
* Waits for CTS to be high
*
* @return CTS value
*/
U8 radio_comm_PollCTS(void)
{
#ifdef RADIO_USER_CFG_USE_GPIO1_FOR_CTS
while(!radio_hal_Gpio1Level())
{
/* Wait...*/
}
ctsWentHigh = 1;
return 0xFF;
#else
return radio_comm_GetResp(0, 0);
#endif
}
/**
* Clears the CTS state variable.
*/
void radio_comm_ClearCTS()
{
ctsWentHigh = 0;
}
#elif (defined SILABS_RADIO_SI4012)
/*!
* Gets a command response from the radio chip
*
* @param byteCount Number of bytes to get from the radio chip
* @param pData Pointer to where to put the data
*
* @return CTS value
*/
U8 radio_comm_GetResp(U8 byteCount, U8* pData)
{
SEGMENT_VARIABLE(ctsVal = 0u, U8, SEG_DATA);
if (qSmbus_SMBusRead(SI4012_SMBUS_ADDRESS, byteCount, pData) != \
SMBUS_RX_FINISHED) {
return FALSE;
}
if (pData[0] == 0x80) {
return TRUE;
}
return FALSE;
}
/*!
* Sends a command to the radio chip
*
* @param byteCount Number of bytes in the command to send to the radio device
* @param pData Pointer to the command to send.
*/
U8 radio_comm_SendCmd(U8 byteCount, U8* pData)
{
if (qSmbus_SMBusWrite(SI4012_SMBUS_ADDRESS, byteCount, pData) != \
SMBUS_TRANSMISSION_OK) {
return FALSE;
}
return TRUE;
}
#endif
/*!
* Sends a command to the radio chip and gets a response
*
* @param cmdByteCount Number of bytes in the command to send to the radio device
* @param pCmdData Pointer to the command data
* @param respByteCount Number of bytes in the response to fetch
* @param pRespData Pointer to where to put the response data
*
* @return CTS value
*/
U8 radio_comm_SendCmdGetResp(U8 cmdByteCount, U8* pCmdData, U8 respByteCount, U8* pRespData)
{
radio_comm_SendCmd(cmdByteCount, pCmdData);
return radio_comm_GetResp(respByteCount, pRespData);
}
/*!
* File:
* radio_comm.h
*
* Description:
* This file contains the RADIO communication layer.
*
* Silicon Laboratories Confidential
* Copyright 2011 Silicon Laboratories, Inc.
*/
#ifndef _RADIO_COMM_H_
#define _RADIO_COMM_H_
/* ======================================= *
* I N C L U D E *
* ======================================= */
/* ======================================= *
* D E F I N I T I O N S *
* ======================================= */
//#define RADIO_CTS_TIMEOUT 255
#define RADIO_CTS_TIMEOUT 10000
/* ======================================= *
* G L O B A L V A R I A B L E S *
* ======================================= */
extern SEGMENT_VARIABLE(radioCmd[16u], U8, SEG_XDATA);
/* ======================================= *
* F U N C T I O N P R O T O T Y P E S *
* ======================================= */
#if (defined SILABS_RADIO_SI446X) || (defined SILABS_RADIO_SI4455)
U8 radio_comm_GetResp(U8 byteCount, U8* pData);
void radio_comm_SendCmd(U8 byteCount, U8* pData);
void radio_comm_ReadData(U8 cmd, BIT pollCts, U8 byteCount, U8* pData);
void radio_comm_WriteData(U8 cmd, BIT pollCts, U8 byteCount, U8* pData);
#elif (defined SILABS_RADIO_SI4012)
U8 radio_comm_GetResp(U8 byteCount, U8* pData);
U8 radio_comm_SendCmd(U8 byteCount, U8* pData);
#endif
U8 radio_comm_PollCTS(void);
U8 radio_comm_SendCmdGetResp(U8 cmdByteCount, U8* pCmdData, \
U8 respByteCount, U8* pRespData);
void radio_comm_ClearCTS(void);
#endif //_RADIO_COMM_H_
/*!
* File:
* radio_hal.c
*
* Description:
* This file contains RADIO HAL.
*
* Silicon Laboratories Confidential
* Copyright 2011 Silicon Laboratories, Inc.
*/
/* ======================================= *
* I N C L U D E *
* ======================================= */
#include "..\..\bsp.h"
/* ======================================= *
* D E F I N I T I O N S *
* ======================================= */
/* ======================================= *
* G L O B A L V A R I A B L E S *
* ======================================= */
/* ======================================= *
* L O C A L F U N C T I O N S *
* ======================================= */
/* ======================================= *
* P U B L I C F U N C T I O N S *
* ======================================= */
void radio_hal_AssertShutdown(void)
{
#if (defined SILABS_PLATFORM_RFSTICK) || (defined SILABS_PLATFORM_LCDBB) || (defined SILABS_PLATFORM_WMB)
RF_PWRDN = 1;
#else
PWRDN = 1;
#endif
}
void radio_hal_DeassertShutdown(void)
{
#if (defined SILABS_PLATFORM_RFSTICK) || (defined SILABS_PLATFORM_LCDBB) || (defined SILABS_PLATFORM_WMB)
RF_PWRDN = 0;
#else
PWRDN = 0;
#endif
}
void radio_hal_ClearNsel(void)
{
RF_NSEL = 0;
}
void radio_hal_SetNsel(void)
{
RF_NSEL = 1;
}
BIT radio_hal_NirqLevel(void)
{
return RF_NIRQ;
}
void radio_hal_SpiWriteByte(U8 byteToWrite)
{
#if (defined SILABS_PLATFORM_RFSTICK) || (defined SILABS_PLATFORM_LCDBB) || (defined SILABS_PLATFORM_WMB)
bSpi_ReadWriteSpi1(byteToWrite);
#else
SpiReadWrite(byteToWrite);
#endif
}
U8 radio_hal_SpiReadByte(void)
{
#if (defined SILABS_PLATFORM_RFSTICK) || (defined SILABS_PLATFORM_LCDBB) || (defined SILABS_PLATFORM_WMB)
return bSpi_ReadWriteSpi1(0xFF);
#else
return SpiReadWrite(0xFF);
#endif
}
void radio_hal_SpiWriteData(U8 byteCount, U8* pData)
{
#if (defined SILABS_PLATFORM_RFSTICK) || (defined SILABS_PLATFORM_LCDBB) || (defined SILABS_PLATFORM_WMB)
vSpi_WriteDataSpi1(byteCount, pData);
#else
SpiWriteData(byteCount, pData);
#endif
}
void radio_hal_SpiReadData(U8 byteCount, U8* pData)
{
#if (defined SILABS_PLATFORM_RFSTICK) || (defined SILABS_PLATFORM_LCDBB) || (defined SILABS_PLATFORM_WMB)
vSpi_ReadDataSpi1(byteCount, pData);
#else
SpiReadData(byteCount, pData);
#endif
}
#ifdef RADIO_DRIVER_EXTENDED_SUPPORT
BIT radio_hal_Gpio0Level(void)
{
BIT retVal = FALSE;
#ifdef SILABS_PLATFORM_DKMB
retVal = FALSE;
#endif
#ifdef SILABS_PLATFORM_UDP
retVal = EZRP_RX_DOUT;
#endif
#if (defined SILABS_PLATFORM_RFSTICK) || (defined SILABS_PLATFORM_LCDBB)
retVal = RF_GPIO0;
#endif
#if (defined SILABS_PLATFORM_WMB930)
retVal = FALSE;
#endif
#if defined (SILABS_PLATFORM_WMB912)
#ifdef SILABS_IO_WITH_EXTENDER
//TODO
retVal = FALSE;
#endif
#endif
return retVal;
}
BIT radio_hal_Gpio1Level(void)
{
BIT retVal = FALSE;
#ifdef SILABS_PLATFORM_DKMB
retVal = FSK_CLK_OUT;
#endif
#ifdef SILABS_PLATFORM_UDP
retVal = FALSE; //No Pop
#endif
#if (defined SILABS_PLATFORM_RFSTICK) || (defined SILABS_PLATFORM_LCDBB) || (defined SILABS_PLATFORM_WMB930)
retVal = RF_GPIO1;
#endif
#if defined (SILABS_PLATFORM_WMB912)
#ifdef SILABS_IO_WITH_EXTENDER
//TODO
retVal = FALSE;
#endif
#endif
return retVal;
}
BIT radio_hal_Gpio2Level(void)
{
BIT retVal = FALSE;
#ifdef SILABS_PLATFORM_DKMB
retVal = DATA_NFFS;
#endif
#ifdef SILABS_PLATFORM_UDP
retVal = FALSE; //No Pop
#endif
#if (defined SILABS_PLATFORM_RFSTICK) || (defined SILABS_PLATFORM_LCDBB) || (defined SILABS_PLATFORM_WMB930)
retVal = RF_GPIO2;
#endif
#if defined (SILABS_PLATFORM_WMB912)
#ifdef SILABS_IO_WITH_EXTENDER
//TODO
retVal = FALSE;
#endif
#endif
return retVal;
}
BIT radio_hal_Gpio3Level(void)
{
BIT retVal = FALSE;
#if (defined SILABS_PLATFORM_RFSTICK) || (defined SILABS_PLATFORM_LCDBB) || (defined SILABS_PLATFORM_WMB930)
retVal = RF_GPIO3;
#elif defined (SILABS_PLATFORM_WMB912)
#ifdef SILABS_IO_WITH_EXTENDER
//TODO
retVal = FALSE;
#endif
#endif
return retVal;
}
#endif
/*!
* File:
* radio_hal.h
*
* Description:
* This file contains RADIO HAL.
*
* Silicon Laboratories Confidential
* Copyright 2011 Silicon Laboratories, Inc.
*/
#ifndef _RADIO_HAL_H_
#define _RADIO_HAL_H_
/* ======================================= *
* I N C L U D E *
* ======================================= */
/* ======================================= *
* D E F I N I T I O N S *
* ======================================= */
/* ======================================= *
* G L O B A L V A R I A B L E S *
* ======================================= */
/* ======================================= *
* F U N C T I O N P R O T O T Y P E S *
* ======================================= */
void radio_hal_AssertShutdown(void);
void radio_hal_DeassertShutdown(void);
void radio_hal_ClearNsel(void);
void radio_hal_SetNsel(void);
BIT radio_hal_NirqLevel(void);
void radio_hal_SpiWriteByte(U8 byteToWrite);
U8 radio_hal_SpiReadByte(void);
void radio_hal_SpiWriteData(U8 byteCount, U8* pData);
void radio_hal_SpiReadData(U8 byteCount, U8* pData);
#ifdef DRIVERS_EXTENDED_SUPPORT
BIT radio_hal_Gpio0Level(void);
BIT radio_hal_Gpio1Level(void);
BIT radio_hal_Gpio2Level(void);
BIT radio_hal_Gpio3Level(void);
#endif
#endif //_RADIO_HAL_H_
/**
* Copyright 2008 Silicon Laboratories, Inc.
* http://www.silabs.com
*
* @file smbus.c
*
* C File Description:
* @brief SMBus interface functions
*
* Project Name: sRange
*
*
* @author Sz. Papp
* @author V. Huszr
*
* @date 2013.05.27.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* This software must be used in accordance with the End User License Agreement.
*/
#include "..\bsp.h"
/** Local functions */
void vSmbus_SMBusStart(void);
void vSmbus_SMBusStop(void);
/**
* Initialize and enable the SMBus interface.
*
* @note Uses T0 timer to generate the appropriate clock source.
* It gives approx. 400 kHz SMBus speed
******************************************************************************/
void vSmbus_InitSMBusInterface()
{
/* Set SMBUS clock speed */
SetSMBUSClk400kHz_24MHZ5;
TR0 = 1; /* START Timer0 */
/* SMBus Slave Inhibit, Clock from T0 overflow */
SMB0CF = 0x40;
/* set auto ACK bit */
SMB0ADM |= 0x01;
/* Enable SMBUS0 in CrossBar */
#ifdef SMBUS_TOGGLE_XBAR_ENABLED
XBR0 |= 0x04;
#endif
/* Disable SMBus interrupt */
EIE1 &= 0xFE;
/* Clear flags */
STA = FALSE;
STO = FALSE;
ACK = FALSE;
SI = FALSE;
/* Enable SMBus peripheral */
SMB0CF |= 0x80;
}
/**
* Disable the SMBus interface.
*
* @note This function doesn't stop/reset T1 timer.
******************************************************************************/
void vSmbus_DisableSMBusInterface()
{
/* Disable SMBus */
STA = FALSE;
STO = FALSE;
ACK = FALSE;
SMB0CF &= 0x7F;
/* Clear IT flag */
SI = FALSE;
TR0 = 0;
/* Disconnect SMBUS0 from CrossBar */
#ifdef SMBUS_TOGGLE_XBAR_ENABLED
XBR0 &= ~(0x04);
#endif
}
/**
* Generate start condition on SMBus.
*
* @note
******************************************************************************/
void vSmbus_SMBusStart()
{
/* Set START bit */
STA = TRUE;
/* wait for the start condition */
while (SI == FALSE);
/* clear interrupt flag */
SI = FALSE;
}
/**
* Generate stop condition on SMBus.
*
* @note
******************************************************************************/
void vSmbus_SMBusStop()
{
/* Stop SMBus transaction */
STO = TRUE;
SI = FALSE;
while (STO == TRUE);
}
/**
* Wait for the SMBus interrupt with timeout.
*
* @return \b FALSE - Timeout occurred without IT. <br>
* \b TRUE - IT occurred within Timeout.
*
* @note
*
******************************************************************************/
BIT gSmbus_SMBusWaitForItWithTimeout()
{
SEGMENT_VARIABLE(busTimeOut, U16, SEG_DATA);
/* reset timeout */
busTimeOut = 0u;
/* wait for the IT */
while ((busTimeOut++ < 0xFFFE) && (SI == FALSE)) ;
if (SI == TRUE) {
return TRUE;
}
/* timeout occured, disable SMBus */
vSmbus_DisableSMBusInterface();
return FALSE;
}
/**
* Read from the SMBus.
*
* @param[in] Address 7bit slave address (7 MSB bit is used)
* @param[in] Length Number of bytes to be read.
* @param[out] pData Array of data bytes read from the slave.
* @return Result of the transaction, refer to CommIF.h.
* @note The function blocks the code until completion.
******************************************************************************/
eSMBusReturnStates qSmbus_SMBusRead(U8 biAddress, U8 biLength, U8 * pboData)
{
/* enable SMBus */
vSmbus_InitSMBusInterface();
/* START condition */
STO = FALSE;
ACK = FALSE;
STA = TRUE;
/* wait for START to be completed */
if (!gSmbus_SMBusWaitForItWithTimeout()) {
return SMBUS_TIMEOUT_ERROR;
}
/* send address byte */
SMB0DAT = (U8) (biAddress << 1u) | 0x01;
/* clear IT flag */
SI = FALSE;
/* delete start bit */
STA = FALSE;
/* wait address byte to be sent */
if (!gSmbus_SMBusWaitForItWithTimeout()) {
return SMBUS_TIMEOUT_ERROR;
}
if (FALSE == ACK) {
/* Slave address is not acknowledged */
vSmbus_DisableSMBusInterface();
return SMBUS_WRONG_SLAVE_ADDRESS;
}
/* read data bytes */
while (biLength--) {
if (biLength > 0u) {
/* More bytes to read */
ACK = TRUE;
} else {
/* Last byte */
ACK = FALSE;
}
/* clear IT flag */
SI = FALSE;
/* wait for receiving the next byte */
if (!gSmbus_SMBusWaitForItWithTimeout()) {
/* timeout occured */
return SMBUS_TIMEOUT_ERROR;
}
*pboData++ = SMB0DAT;
}
/* all data byte read */
vSmbus_SMBusStop();
vSmbus_DisableSMBusInterface();
return SMBUS_RX_FINISHED;
}
/**
* Send a given number of bytes on SMBus to the given address.
*
* @param[in] Address 7bit slave address (7 MSB bit is used).
* @param[in] Length Number of bytes to be sent.
* @param[in] pData Pointer to data bytes to be sent.
* @return Result of the transaction, refer to CommIF.h
* @note The function blocks the flow until completion.
******************************************************************************/
eSMBusReturnStates qSmbus_SMBusWrite(U8 biAddress, U8 biLength, U8 * pbiData)
{
/* enable SMBus */
vSmbus_InitSMBusInterface();
/* START condition */
STO = FALSE;
ACK = FALSE;
STA = TRUE;
/* wait for START to be completed */
if (!gSmbus_SMBusWaitForItWithTimeout()) {
return SMBUS_TIMEOUT_ERROR;
}
/* send address byte */
SMB0DAT = (U8) (biAddress << 1u) & 0xFE;
/* clear IT flag */
SI = FALSE;
/* delete start bit */
STA = FALSE;
/* wait address byte to be sent */
if (!gSmbus_SMBusWaitForItWithTimeout()) {
return SMBUS_TIMEOUT_ERROR;
}
if (FALSE == ACK) {
/* Slave address is not acknowledged */
vSmbus_DisableSMBusInterface();
return SMBUS_WRONG_SLAVE_ADDRESS;
}
/* send data bytes */
while (biLength--) {
/* send next data bytes */
SMB0DAT = *pbiData++;
/* clear IT flag */
SI = FALSE;
/* wait data to be sent */
if (!gSmbus_SMBusWaitForItWithTimeout()) {
return SMBUS_TIMEOUT_ERROR;
}
if (TRUE == ARBLOST) {
/* arbritation lost */
vSmbus_DisableSMBusInterface();
return SMBUS_ARBITRATION_LOST;
}
}
/* all data byte sent */
vSmbus_SMBusStop();
vSmbus_DisableSMBusInterface();
return SMBUS_TRANSMISSION_OK;
}
/**
* Copyright 2008 Silicon Laboratories, Inc.
* http://www.silabs.com
*
* @file smbus.h
*
* C File Description:
* @brief SMBus interface functions
*
* Project Name: sRange
*
*
* @author Sz. Papp
* @author V. Huszr
*
* @date 2013.05.27.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* This software must be used in accordance with the End User License Agreement.
*/
#ifndef SMBUS_H_
#define SMBUS_H_
/*****************************************************************************
* Global Macros & Definitions
*****************************************************************************/
/*! Macro to set the SMBUS clock 400kHz (with 24.5MHz internal precision clock) */
#if !(defined SILABS_MCU_F912)
#define SetSMBUSClk400kHz_24MHZ5 CKCON &= 0xFB; CKCON |= 0x04; \
TH0 = 0xEC; TMOD &= 0xF0; \
TMOD |= 0x02
#else
#define SetSMBUSClk400kHz_24MHZ5 CKCON &= 0xFB; CKCON |= 0x04; \
TH0 = 0xEA; TMOD &= 0xF0; \
TMOD |= 0x02
#endif
/* SMBus function map for DCPModule */
//todo: Move it to DCP specific header file
#define Comm_IF_InitSMBusInterface() vSmbus_InitSMBusInterface()
#define Comm_IF_DisableSMBusInterface() vSmbus_DisableSMBusInterface()
#define Comm_IF_SMBusStart() vSmbus_SMBusStart()
#define Comm_IF_SMBusStop() vSmbus_SMBusStop()
#define Comm_IF_SMBusWriteByte(biData) qSmbus_SMBusWriteByte(biData)
#define Comm_IF_SMBusReadByte(giAckReq) bSmbus_SMBusReadByte(giAckReq)
#define Comm_IF_SMBusWrite(biAddress, biLength, pbiData) \
qSmbus_SMBusWrite(biAddress, biLength, pbiData)
#define Comm_IF_SMBusRead(biAddress, biLength, pboData) \
qSmbus_SMBusRead(biAddress, biLength, pboData)
#define Comm_IF_SMBusWaitForItWithTimeout() \
gSmbus_SMBusWaitForItWithTimeout()
/*****************************************************************************
* Global Enums & Typedefs
*****************************************************************************/
typedef enum
{
SMBUS_TRANSMISSION_OK,
SMBUS_RX_FINISHED,
SMBUS_ARBITRATION_LOST,
SMBUS_TIMEOUT_ERROR,
SMBUS_BUSY,
SMBUS_WRONG_SLAVE_ADDRESS,
SMBUS_NACK_RECEIVED,
SMBUS_ACK_RECEIVED,
SMBUS_GENERAL_ERROR
} eSMBusReturnStates;
/*****************************************************************************
* Global Function Declarations
*****************************************************************************/
void vSmbus_InitSMBusInterface(void);
void vSmbus_DisableSMBusInterface(void);
BIT gSmbus_SMBusWaitForItWithTimeout(void);
eSMBusReturnStates qSmbus_SMBusWrite(U8 biAddress, U8 biLength, U8 * pbiData);
eSMBusReturnStates qSmbus_SMBusRead(U8 biAddress, U8 biLength, U8 * pboData);
#endif /* SMBUS_H_ */
/*! @file spi.c
* @brief This file contains functions for controlling SPI0 and SPI1 interfaces.
*
* @b COPYRIGHT
* @n Silicon Laboratories Confidential
* @n Copyright 2012 Silicon Laboratories, Inc.
* @n http://www.silabs.com
*/
#include "..\bsp.h"
/*------------------------------------------------------------------------*/
/* Global variables */
/*------------------------------------------------------------------------*/
#if ((defined SILABS_MCU_DC_MLCD) || (defined SILABS_LCD_DOG_GLCD))
/**< Current state of the NSEL of SPI0 */
SEGMENT_VARIABLE(bSpi_SelectStateSpi0, U8 , SEG_DATA);
/**< Current state of SPI0 */
BIT gSpi_Spi0Disabled;
#endif
/**< Current state of the NSEL of SPI1 */
SEGMENT_VARIABLE(bSpi_SelectStateSpi1, U8 , SEG_DATA);
/**< Current state of SPI1 */
BIT gSpi_Spi1Disabled;
/*------------------------------------------------------------------------*/
/* Function implementations */
/*------------------------------------------------------------------------*/
#if ((defined SILABS_MCU_DC_MLCD) || (defined SILABS_LCD_DOG_GLCD))
/*!
* This function is used to read/write one byte from/to SPI0.
*
* @param[in] biDataIn Data to be sent.
* @return Read value of the SPI port after writing on it.
*/
#if !(defined SILABS_PLATFORM_WMB912)
U8 bSpi_ReadWriteSpi0(U8 biDataIn)
{
SEGMENT_VARIABLE(bValue, U8, SEG_DATA);
BIT gRestoreEA;
#ifdef SILABS_MCU_F960
SEGMENT_VARIABLE(bRestoreSfrPage, U8, SEG_DATA);
#endif
// disable interrupts during SPI transfer
gRestoreEA = EA;
EA = 0;
#ifdef SILABS_MCU_F960
// save SFR page and switch to SPI1 page
bRestoreSfrPage = SFRPAGE;
SFRPAGE = LEGACY_PAGE ;
#endif
// Send SPI data using double buffered write
SPIF0 = 0; // clear SPIF
SPI0DAT = ( biDataIn ); // write data register
while (!TXBMT0); // wait on TXBMT
while ((SPI0CFG & M_SPIBSY0) == M_SPIBSY0); // wait on SPIBSY
bValue = SPI0DAT; // read value
SPIF0 = 0; // leave SPIF cleared
#ifdef SILABS_MCU_F960
// Restore SFR page after SPI transfer
SFRPAGE = bRestoreSfrPage;
#endif
// Restore interrupts after SPI transfer
EA = gRestoreEA;
return bValue;
}
#endif //#if !(defined SILABS_PLATFORM_WMB912)
#endif //#if ((defined SILABS_MCU_DC_MLCD) || (defined SILABS_LCD_DOG_GLCD))
/*!
* This function is used to read/write one byte from/to SPI1.
*
* @param[in] biDataIn Data to be sent.
* @return Read value of the SPI port after writing on it.
*/
U8 bSpi_ReadWriteSpi1(U8 biDataIn)
{
SEGMENT_VARIABLE(bValue, U8, SEG_DATA);
BIT gRestoreEA;
#ifdef SILABS_MCU_F960
SEGMENT_VARIABLE(bRestoreSfrPage, U8, SEG_DATA);
#endif
/* disable interrupts during SPI transfer */
gRestoreEA = EA;
ENTER_CRITICAL_SECTION;
#ifdef SILABS_MCU_F960
// save SFR page and switch to SPI1 page
bRestoreSfrPage = SFRPAGE;
SFRPAGE = LEGACY_PAGE ;
#endif
// Send SPI data using double buffered write
SPIF1 = 0; // clear SPIF
SPI1DAT = ( biDataIn ); // write data register
while (!TXBMT1); // wait on TXBMT
while ((SPI1CFG & M_SPIBSY1) == M_SPIBSY1); // wait on SPIBSY
bValue = SPI1DAT; // read value
SPIF1 = 0; // leave SPIF cleared
// Restore interrupts after SPI transfer
EA = gRestoreEA;
return bValue;
}
#if ((defined SILABS_MCU_DC_MLCD) || (defined SILABS_LCD_DOG_GLCD))
/*!
* This function is used to send data over SPI0 no response expected.
*
* @param[in] biDataInLength The length of the data.
* @param[in] *pabiDataIn Pointer to the first element of the data.
*
* @return None
*/
void vSpi_WriteDataSpi0(U8 biDataInLength, U8 *pabiDataIn)
{
while (biDataInLength--) {
bSpi_ReadWriteSpi0(*pabiDataIn++);
}
}
#endif
/*!
* This function is used to send data over SPI1 no response expected.
*
* @param[in] biDataInLength The length of the data.
* @param[in] *pabiDataIn Pointer to the first element of the data.
*
* @return None
*/
void vSpi_WriteDataSpi1(U8 biDataInLength, U8 *pabiDataIn)
{
#ifdef SILABS_MCU_F960
#warning Check if implemenations of DMA makes sense for SPI on F960!
#endif
while (biDataInLength--) {
bSpi_ReadWriteSpi1(*pabiDataIn++);
}
}
#if ( ((defined SILABS_MCU_DC_MLCD) || (defined SILABS_LCD_DOG_GLCD)) && !(defined SILABS_PLATFORM_WMB912) )
/*!
* This function is used to read data from SPI0.
*
* \param[in] biDataOutLength The length of the data.
* \param[out] *paboDataOut Pointer to the first element of the response.
*
* \return None
*/
void vSpi_ReadDataSpi0(U8 biDataOutLength, U8 *paboDataOut)
{
while (biDataOutLength--) {
*paboDataOut++ = bSpi_ReadWriteSpi0(0xFF);
}
}
#endif
/*!
* This function is used to read data from SPI1.
*
* \param[in] biDataOutLength The length of the data.
* \param[out] *paboDataOut Pointer to the first element of the response.
*
* \return None
*/
void vSpi_ReadDataSpi1(U8 biDataOutLength, U8 *paboDataOut)
{
#ifdef SILABS_MCU_F960
#warning Check if implemenations of DMA makes a sense for SPI on F960!
#endif
// send command and get response from the radio IC
while (biDataOutLength--) {
*paboDataOut++ = bSpi_ReadWriteSpi1(0xFF);
}
}
/**
* Pull down nSEL of the selected device.
*
* @param[in] qiSelect Device select.
*
* @note Input: qiSelect <br> 0 - \b DUT <br> 1 - \b LCD <br>
*
******************************************************************************/
void vSpi_ClearNsel(eSpi_Nsel qiSelect)
{
switch (qiSelect)
{
case eSpi_Nsel_RF:
RF_NSEL = FALSE;
break;
#if ((defined SILABS_MCU_DC_MLCD) || (defined SILABS_LCD_DOG_GLCD))
case eSpi_Nsel_LCD:
LCD_NSEL = FALSE;
break;
#endif
default:
break;
}
}
/**
* Pull-up nSEL of the selected device.
*
* @param[in] qiSelect Device select.
*
* @note Input: qiSelect <br> 0 - \b DUT <br> 1 - \b LCD <br>
*
******************************************************************************/
void vSpi_SetNsel(eSpi_Nsel qiSelect)
{
switch (qiSelect)
{
case eSpi_Nsel_RF:
RF_NSEL = TRUE;
break;
#if ((defined SILABS_MCU_DC_MLCD) || (defined SILABS_LCD_DOG_GLCD))
case eSpi_Nsel_LCD:
LCD_NSEL = TRUE;
break;
#endif
default:
break;
}
}
#ifdef SPI_DRIVER_EXTENDED_SUPPORT
/**
* Writes one byte to the SPI1 peripheral and reads one byte at the same time.
*
* @param[in] biDataIn Data to be written.
*
* @return Data read from SPI1.
*
* @note
******************************************************************************/
U8 bSpi_ReadWriteByteSpi1(U8 biDataIn)
{
SEGMENT_VARIABLE(bReadValue, U8, SEG_DATA);
/* disable global interrupts */
ENTER_CRITICAL_SECTION;
/* select device */
vSpi_ClearNsel( eSpi_Nsel_RF );
bReadValue = bSpi_ReadWriteSpi1(biDataIn);
vSpi_SetNsel( eSpi_Nsel_RF );
/* enable global interrupts */
EXIT_CRITICAL_SECTION;
return bReadValue;
}
/**
* Read/Write 16 bits to the selected device.
*
* @param[in] biAddress Address of the register.
*
* @param[in] biDataIn Data to be written.
*
* @return Data read from SPI1.
*
* @note
******************************************************************************/
U16 bSpi_ReadWriteWordSpi1(U8 biAddress, U8 biDataIn)
{
SEGMENT_VARIABLE(rwReadValue, UU16, SEG_DATA);
/* disable global interrupts */
ENTER_CRITICAL_SECTION;
/* select device */
vSpi_ClearNsel( eSpi_Nsel_RF );
rwReadValue.U8[MSB] = bSpi_ReadWriteSpi1(biAddress);
rwReadValue.U8[LSB] = bSpi_ReadWriteSpi1(biDataIn);
vSpi_SetNsel( eSpi_Nsel_RF );
/* enable global interrupts */
EXIT_CRITICAL_SECTION;
return rwReadValue.U16;
}
/**
* Read/Write several number of bytes into the selected device.
*
* @param[in] biAddress Starting address; MSB defines whether it is read or write!
* @param[in] biLength Number of registers have to be written.
* @param[in] pbiData Pointer to the source of the registers.
* @param[out] pboData Bytes read during transaction.
*
* @note Read or write bit has to be set!
******************************************************************************/
void bSpi_ReadWriteBurstSpi1(U8 biAddress, U8 biLength, U8 *pbiData, U8 *pboData)
{
SEGMENT_VARIABLE(ii, U8, SEG_DATA);
/* disable global interrupts */
ENTER_CRITICAL_SECTION;
/* select device */
vSpi_ClearNsel( eSpi_Nsel_RF );
/* send the register address */
bSpi_ReadWriteSpi1(biAddress);
/* send register content */
for (ii = 0u; ii < biLength; ++ii) {
*pboData++ = bSpi_ReadWriteSpi1(*pbiData++);
}
vSpi_SetNsel( eSpi_Nsel_RF );
/* enable global interrupts */
EXIT_CRITICAL_SECTION;
}
#if (!(defined SILABS_PLATFORM_DISABLE_SPI0) && ((defined SILABS_MCU_DC_MLCD) || (defined SILABS_LCD_DOG_GLCD)))
/*!
* This function is used to enable SPI0 and associate to XBAR.
*
* @return None.
*/
void vSpi_EnableSpi0(void)
{
#ifdef SILABS_MCU_F960
SEGMENT_VARIABLE(bRestoreSfrPage, U8, SEG_DATA);
#endif
#ifdef SILABS_MCU_F960
// save SFR page and switch to SPI1 page
bRestoreSfrPage= SFRPAGE;
SFRPAGE = LEGACY_PAGE;
#endif
//enable SPI port
SPI0CN |= M_SPI0EN;
//associate to the XBAR
XBR0 |= M_SPI0E;
//configure IO pins
#if (defined SILABS_PLATFORM_RFSTICK)
P0SKIP &= (~M_P0_SPI0_SCK) & (~M_P0_SPI0_MISO) & (~M_P0_SPI0_MOSI);
#else
PXSKIP_SPI0_MOSI &= (~MASK_SPI0_MOSI);
#if !(defined SILABS_PLATFORM_WMB912)
PXSKIP_SPI0_MISO &= (~MASK_SPI0_MISO);
#endif
PXSKIP_SPI0_SCK &= (~MASK_SPI0_SCK);
#endif
//set default state for pins
SPI0_SCK = 1;
SPI0_MOSI = 1;
gSpi_Spi0Disabled = 0;
#ifdef SILABS_MCU_F960
// Restore SFR page after SPI transfer
SFRPAGE = bRestoreSfrPage;
#endif
}
#endif
/*!
* This function is used to enable SPI1 and associate to XBAR.
*
* @return None.
*/
void vSpi_EnableSpi1(void)
{
#ifdef SILABS_MCU_F960
SEGMENT_VARIABLE(bRestoreSfrPage, U8, SEG_DATA);
#endif
#ifdef SILABS_MCU_F960
// save SFR page and switch to SPI1 page
bRestoreSfrPage= SFRPAGE;
SFRPAGE = SPI1_PAGE;
#endif
//enable SPI port
SPI1CN |= M_SPI1EN;
#ifdef SILABS_MCU_F960
SFRPAGE = LEGACY_PAGE;
#endif
//associate to the XBAR
XBR1 |= M_SPI1E;
//configure IO pins
#if (defined SILABS_PLATFORM_RFSTICK)
P1SKIP &= (~M_P1_SPI1_SCK) & (~M_P1_SPI1_MISO) & (~M_P1_SPI1_MOSI);
#else
PXSKIP_SPI1_MOSI &= (~MASK_SPI1_MOSI);
PXSKIP_SPI1_MISO &= (~MASK_SPI1_MISO);
PXSKIP_SPI1_SCK &= (~MASK_SPI1_SCK);
#endif
//set default state for pins
SPI1_SCK = 1;
SPI1_MOSI = 1;
gSpi_Spi1Disabled = 0;
#ifdef SILABS_MCU_F960
// Restore SFR page after SPI transfer
SFRPAGE = bRestoreSfrPage;
#endif
}
#if (!(defined SILABS_PLATFORM_DISABLE_SPI0) && ((defined SILABS_MCU_DC_MLCD) || (defined SILABS_LCD_DOG_GLCD)))
/*!
* This function is used to disable SPI0 and disconnect from XBAR.
*
* @return None.
*/
void vSpi_DisableSpi0(void)
{
#ifdef SILABS_MCU_F960
SEGMENT_VARIABLE(bRestoreSfrPage, U8, SEG_DATA);
#endif
#ifdef SILABS_MCU_F960
// save SFR page and switch to SPI1 page
bRestoreSfrPage= SFRPAGE;
SFRPAGE = LEGACY_PAGE;
#endif
//disable SPI port
SPI0CN &= (~M_SPI0EN);
//disconnect from XBAR
XBR0 &= (~M_SPI0E);
//configure IO port directions
#if (defined SILABS_PLATFORM_RFSTICK)
P0SKIP |= M_P0_SPI0_SCK | M_P0_SPI0_MISO | M_P0_SPI0_MOSI;
#else
PXSKIP_SPI0_MOSI |= (MASK_SPI0_MOSI);
#if !(defined SILABS_PLATFORM_WMB912)
PXSKIP_SPI0_MISO |= (MASK_SPI0_MISO);
#endif
PXSKIP_SPI0_SCK |= (MASK_SPI0_SCK);
#endif //set default state for the pins
SPI0_SCK = FALSE;
SPI0_MOSI = TRUE;
gSpi_Spi0Disabled = FALSE;
#ifdef SILABS_MCU_F960
// Restore SFR page after SPI transfer
SFRPAGE = bRestoreSfrPage;
#endif
}
#endif
/*!
* This function is used to disable SPI1 and disconnect from XBAR.
*
* @return None.
*/
void vSpi_DisableSpi1(void)
{
#ifndef SPI_PERIPHERALS_ALWAYS_ENABLED
#ifdef SILABS_MCU_F960
SEGMENT_VARIABLE(bRestoreSfrPage, U8, SEG_DATA);
#endif
#ifdef SILABS_MCU_F960
// save SFR page and switch to SPI1 page
bRestoreSfrPage= SFRPAGE;
SFRPAGE = SPI1_PAGE;
#endif
//disable SPI port
SPI1CN &= (~M_SPI1EN);
#ifdef SILABS_MCU_F960
SFRPAGE = LEGACY_PAGE;
#endif
//disconnect from XBAR
XBR1 &= (~M_SPI1E);
//configure IO port directions
#if (defined SILABS_PLATFORM_RFSTICK)
P1SKIP |= M_P1_SPI1_SCK | M_P1_SPI1_MISO | M_P1_SPI1_MOSI;
#else
PXSKIP_SPI1_MOSI |= (MASK_SPI1_MOSI);
PXSKIP_SPI1_MISO |= (MASK_SPI1_MISO);
PXSKIP_SPI1_SCK |= (MASK_SPI1_SCK);
#endif //set default state for the pins
//set default state for the pins
SPI1_SCK = FALSE;
SPI1_MOSI = TRUE;
gSpi_Spi1Disabled = TRUE;
#ifdef SILABS_MCU_F960
// Restore SFR page after SPI transfer
SFRPAGE = bRestoreSfrPage;
#endif
#endif
}
#if (!(defined SILABS_PLATFORM_DISABLE_SPI0) && ((defined SILABS_MCU_DC_MLCD) || (defined SILABS_LCD_DOG_GLCD)))
/*!
* This function is used to read one byte from SPI0 using bitbang method.
*
* @return Read byte
*/
U8 bSpi_ReadByteBitbangSpi0(void)
{
SEGMENT_VARIABLE(bReadByte, U8, SEG_DATA);
SEGMENT_VARIABLE(bCnt, U8, SEG_DATA);
bReadByte = FALSE;
SPI0_SCK = TRUE;
NOP();
NOP();
SPI0_SCK = FALSE;
NOP();
for(bCnt = 0; bCnt < 8; bCnt++)
{
SPI0_SCK = TRUE;
bReadByte <<= 1;
//take sample
#if !(defined SILABS_PLATFORM_WMB912)
if(TRUE == SPI0_MISO)
{
bReadByte |= 0x01;
}
#endif
SPI0_SCK = FALSE;
}
return bReadByte;
}
#endif
/*!
* This function is used to read one byte from SPI1 using bitbang method.
*
* @return Read byte
*/
U8 bSpi_ReadByteBitbangSpi1(void)
{
SEGMENT_VARIABLE(bReadByte, U8, SEG_DATA);
SEGMENT_VARIABLE(bCnt, U8, SEG_DATA);
bReadByte = FALSE;
SPI1_SCK = TRUE;
NOP();
NOP();
SPI1_SCK = FALSE;
NOP();
for(bCnt = 0; bCnt < 8; bCnt++)
{
SPI1_SCK = TRUE;
bReadByte <<= 1;
//take sample
if(TRUE == SPI1_MISO)
{
bReadByte |= 0x01;
}
SPI1_SCK = FALSE;
}
return bReadByte;
}
/*!
* This function is used to write specified number of bits to SPI1 using bitbang method.
*
* @param[in] biDataIn Input byte of data bits
* @param[out] biNumOfBits Number of bits to be written to SPI
*
* @return None
*/
void vSpi_WriteBitsBitbangSpi1(U8 biDataIn, U8 biNumOfBits)
{
SEGMENT_VARIABLE(bCnt, U8, SEG_DATA);
SEGMENT_VARIABLE(bMask, U8, SEG_DATA);
bMask = (0x01 << (biNumOfBits-1));
for(bCnt = 0; bCnt < biNumOfBits; bCnt++)
{
SPI1_SCK = FALSE;
if((biDataIn & bMask) != 0u)
{
SPI1_MOSI = TRUE;
}
else
{
SPI1_MOSI = FALSE;
}
//clock pulse to sample
SPI1_SCK = TRUE;
bMask >>= 1;
}
SPI1_SCK = FALSE;
}
#endif
#if ((defined SPI_DRIVER_EXTENDED_SUPPORT) || (defined SILABS_PLATFORM_WMB912))
#if (!(defined SILABS_PLATFORM_DISABLE_SPI0) && ((defined SILABS_MCU_DC_MLCD) || (defined SILABS_LCD_DOG_GLCD)))
/*!
* This function is used to write specified number of bits to SPI0 using bitbang method.
*
* @param[in] biDataIn Input byte of data bits
* @param[out] biNumOfBits Number of bits to be written to SPI
*
* @return None
*/
void vSpi_WriteBitsBitbangSpi0(U8 biDataIn, U8 biNumOfBits)
{
SEGMENT_VARIABLE(bCnt, U8, SEG_DATA);
SEGMENT_VARIABLE(bMask, U8, SEG_DATA);
bMask = (0x01 << (biNumOfBits-1));
for(bCnt = 0; bCnt < biNumOfBits; bCnt++)
{
SPI0_SCK = FALSE;
if((biDataIn & bMask) != 0u)
{
SPI0_MOSI = TRUE;
}
else
{
SPI0_MOSI = FALSE;
}
//clock pulse to sample
SPI0_SCK = TRUE;
bMask >>= 1;
}
SPI0_SCK = FALSE;
}
#endif //#if (!(defined SILABS_PLATFORM_DISABLE_SPI0) && ((defined SILABS_MCU_DC_MLCD) || (defined SILABS_LCD_DOG_GLCD)))
#endif //#if ((defined SPI_DRIVER_EXTENDED_SUPPORT) || (defined SILABS_PLATFORM_WMB912))
\ No newline at end of file
/*! @file spi.h
* @brief This file is the interface file for SPI0 and SPI1 routines.
*
* @b COPYRIGHT
* @n Silicon Laboratories Confidential
* @n Copyright 2012 Silicon Laboratories, Inc.
* @n http://www.silabs.com
*/
#ifndef SPI_H
#define SPI_H
/*------------------------------------------------------------------------*/
/* Global typedefs & definitions */
/*------------------------------------------------------------------------*/
/*! SPI device select enum */
typedef enum
{
eSpi_Nsel_RF,
eSpi_Nsel_LCD
} eSpi_Nsel;
/*------------------------------------------------------------------------*/
/* External variables */
/*------------------------------------------------------------------------*/
#if ((defined SILABS_MCU_DC_MLCD) || (defined SILABS_LCD_DOG_GLCD))
extern SEGMENT_VARIABLE(bSpi_SelectStateSpi0, U8 , SEG_DATA);
extern BIT gSpi_Spi0Disabled;
#endif
extern SEGMENT_VARIABLE(bSpi_SelectStateSpi1, U8 , SEG_DATA);
extern BIT gSpi_Spi1Disabled;
/*------------------------------------------------------------------------*/
/* Function prototypes */
/*------------------------------------------------------------------------*/
#ifdef SPI_DRIVER_EXTENDED_SUPPORT
#if ((defined SILABS_MCU_DC_MLCD) || (defined SILABS_LCD_DOG_GLCD))
void vSpi_EnableSpi0(void);
void vSpi_DisableSpi0(void);
U8 bSpi_ReadByteBitbangSpi0(void);
void vSpi_WriteBitsBitbangSpi0(U8 biDataIn, U8 biNumOfBits);
#endif
void vSpi_EnableSpi1(void);
void vSpi_DisableSpi1(void);
U8 bSpi_ReadByteBitbangSpi1(void);
void vSpi_WriteBitsBitbangSpi1(U8 biDataIn, U8 biNumOfBits);
U8 bSpi_ReadWriteByteSpi1(U8 biDataIn);
U16 bSpi_ReadWriteWordSpi1(U8 biAddress, U8 biDataIn);
void bSpi_ReadWriteBurstSpi1(U8 biAddress, U8 biLength, U8 *pbiData, U8 *pboData);
#endif
#if ((defined SPI_DRIVER_EXTENDED_SUPPORT) || (defined SILABS_PLATFORM_WMB912))
#if ((defined SILABS_MCU_DC_MLCD) || (defined SILABS_LCD_DOG_GLCD))
void vSpi_WriteBitsBitbangSpi0(U8 biDataIn, U8 biNumOfBits);
#endif
#endif
#if ((defined SILABS_MCU_DC_MLCD) || (defined SILABS_LCD_DOG_GLCD))
void vSpi_WriteDataSpi0(U8 biDataInLength, U8 *pabiDataIn);
#if !(defined SILABS_PLATFORM_WMB912)
void vSpi_ReadDataSpi0(U8 biDataOutLength, U8 *paboDataOut);
U8 bSpi_ReadWriteSpi0(U8 biDataIn);
#else //#if !(defined SILABS_PLATFORM_WMB912)
#define bSpi_ReadWriteSpi0(biDataIn) vSpi_WriteBitsBitbangSpi0(biDataIn, 8u)
#endif //#if !(defined SILABS_PLATFORM_WMB912)
#endif //#if ((defined SILABS_MCU_DC_MLCD) || (defined SILABS_LCD_DOG_GLCD))
void vSpi_WriteDataSpi1(U8 biDataInLength, U8 *pabiDataIn);
void vSpi_ReadDataSpi1(U8 biDataOutLength, U8 *paboDataOut);
U8 bSpi_ReadWriteSpi1(U8 biDataIn);
void vSpi_ClearNsel(eSpi_Nsel qiSelect);
void vSpi_SetNsel(eSpi_Nsel qiSelect);
#endif
/*! @file timer.c
* @brief This file contains the interface functions of the timers.
*
* @b COPYRIGHT
* @n Silicon Laboratories Confidential
* @n Copyright 2012 Silicon Laboratories, Inc.
* @n http://www.silabs.com
*/
#include "..\bsp.h"
/*------------------------------------------------------------------------*/
/* Global variables */
/*------------------------------------------------------------------------*/
SEGMENT_VARIABLE(wwTmr_Tmr2Periode , UU16, SEG_DATA) = {lTmr_Tmr2CntMax_c}; /**< Timer 2 period (1ms) */
/*------------------------------------------------------------------------*/
/* Function implementations */
/*------------------------------------------------------------------------*/
/*!
* This function is used to start Timer 2 in the specified mode.
*
* @param[in] biPrescaler Prescaler value of timer (use predefined constants: bTmr_Tmr2One_c, bTmr_Tmr2Both_c)
* @param[in] wwiPeriod The duration of the timing
* @param[in] biItEnable Enables timer IT if TRUE, disables it if FALSE
* @param[in] biExtClkSel External clock select (use predefined constants: bTmr_TxXCLK_00_c etc.)
*
* @return None.
*/
void vTmr_StartTmr2(U8 biPrescaler, U16 wiPeriod, U8 biItEnable, U8 biExtClkSel)
{
//setup timer
if (biPrescaler == eTmr_SysClk_c)
{
CKCON |= (M_T2MH | M_T2ML);
}
else
{
CKCON &= ~(M_T2MH | M_T2ML);
}
TMR2CN = biExtClkSel & M_T2XCLK;
//set time period
wiPeriod = 65535u - wiPeriod;
TMR2 = wiPeriod;
TMR2RL = wiPeriod;
//enable IT if needed
if (biItEnable)
{
mTmr_EnableTmr2It();
}
else
{
mTmr_DisableTmr2It();
}
mTmr_EnableTmr2();
}
#ifdef TIMER_DRIVER_EXTENDED_SUPPORT
/*!
* This function is used to check if Timer 2 is expired.
*
* @return True if timer is expired (also stops the timer).
* @note Function clears the IT status flag as well.
*/
BIT gTmr_Tmr2Expired(void)
{
if( TF2H == 0)
{
return FALSE;
}
else
{
mTmr_StopTmr2();
return TRUE;
}
}
/*!
* This function is used to start Timer 3 in the specified mode.
*
* @param[in] biPrescaler Prescaler value of timer (use predefined constants: bTmr_Tmr3One_c, bTmr_Tmr3Both_c)
* @param[in] wiPeriod The duration of the timing
* @param[in] biItEnable Enables timer IT if TRUE, disables it if FALSE
* @param[in] biExtClkSel External clock select (use predefined constants: bTmr_TxXCLK_00_c etc.)
*
* @return None.
*/
void vTmr_StartTmr3(U8 biPrescaler, U16 wiPeriod, U8 biItEnable, U8 biExtClkSel)
{
#ifdef SILABS_MCU_F960
SEGMENT_VARIABLE(bRestoreSfrPage, U8, SEG_DATA);
bRestoreSfrPage = SFRPAGE;
SFRPAGE = LEGACY_PAGE;
#endif //#ifdef SILABS_MCU_F960
/* Configure the timer3 operation */
vTmr_StartTmr3_phaseConfigure(biPrescaler, wiPeriod, biItEnable, biExtClkSel, FALSE );
vTmr_StartTmr3_phaseStart(wiPeriod);
#ifdef SILABS_MCU_F960
// Restore SFR page after SPI transfer
SFRPAGE = bRestoreSfrPage;
#endif //#ifdef SILABS_MCU_F960
}
/*!
* This function is used to configure Timer 3 in the specified mode without starting it.
*
* @param[in] biPrescaler Prescaler value of timer (use predefined constants: bTmr_Tmr3One_c, bTmr_Tmr3Both_c)
* @param[in] wiPeriod The duration of the timing
* @param[in] biItEnable Enables timer IT if TRUE, disables it if FALSE
* @param[in] biExtClkSel External clock select (use predefined constants: bTmr_TxXCLK_00_c etc.)
* @param[in] biSetItPriorityHigh If TRUE sets the Timer3 IT priority to High
*
* @return None.
*/
void vTmr_StartTmr3_phaseConfigure(U8 biPrescaler, U16 wiPeriod, U8 biItEnable, U8 biExtClkSel, U8 biSetItPriorityHigh)
{
if (biPrescaler == eTmr_SysClk_c)
{
CKCON |= (M_T3MH | M_T3ML);
}
else
{
CKCON &= ~(M_T3MH | M_T3ML);
}
#if 0 //TODO: Left here for debug purposes, remove if released
/* Set T3 to run from SYSCLK */
CKCON &= 0x3F;
CKCON |= 0x40;
#endif
TMR3CN = biExtClkSel & M_T3XCLK;
#if 0 //TODO: Left here for debug purposes, remove if released
/* Reset Timer3 flags, Stop mode, AutoReload */
TMR3CN = 0u;
#endif
wiPeriod = 65535u - wiPeriod;
TMR3 = wiPeriod;
TMR3RL = wiPeriod;
#if 0 //TODO: Left here for debug purposes, remove if released
/* Set Initial Value */
TMR3 = Reload;
/* Set Reload value */
TMR3RL = Reload;
#endif
if ( biSetItPriorityHigh )
{
/* Set Timer3 IT priority to High */
EIP1 |= 0x80;
}
//enable IT if needed
if( biItEnable == 1 )
{
mTmr_EnableTmr3It();
}
else
{
mTmr_DisableTmr3It();
}
#if 0 //TODO: Left here for debug purposes, remove if released
/* Enable Timer3 IT */
EIE1 |= 0x80;
#endif
}
/**
* Starts Timer3 HW peripheral
*
* @param Reload Timer Reload Value
*
* @author Sz. Papp
*
* @note
*
*****************************************************************************/
void vTmr_StartTmr3_phaseStart(U16 wiPeriod)
{
/* Set Reload value */
wiPeriod = 65535u - wiPeriod;
TMR3RL = wiPeriod;
mTmr_EnableTmr3();
#if 0 //TODO: Left here for debug purposes, remove if released
/* Start Timer3 */
TMR3CN |= 0x04;
#endif
}
/*!
* This function is used to check if Timer 3 is expired.
*
* @return True if timer is expired (also stops the timer).
* @note Function clears the IT status flag as well.
*/
BIT gTmr_Tmr3Expired(void)
{
#ifdef SILABS_MCU_F960
SEGMENT_VARIABLE(bRestoreSfrPage, U8, SEG_DATA);
bRestoreSfrPage = SFRPAGE;
SFRPAGE = LEGACY_PAGE;
#endif //#ifdef SILABS_MCU_F960
if( (TMR3CN & M_TF3H) == 0)
{
return 0;
}
else
{
mTmr_StopTmr3();
return 1;
}
#ifdef SILABS_MCU_F960
// Restore SFR page after SPI transfer
SFRPAGE = bRestoreSfrPage;
#endif //#ifdef SILABS_MCU_F960
}
#endif //#ifdef TIMER_DRIVER_EXTENDED_SUPPORT
/*! @file isr.c
* @brief Header file of timer routines and definitions.
*
* @b COPYRIGHT
* @n Silicon Laboratories Confidential
* @n Copyright 2012 Silicon Laboratories, Inc.
* @n http://www.silabs.com
*/
#ifndef TIMER_H_
#define TIMER_H_
/*------------------------------------------------------------------------*/
/* Global definitions */
/*------------------------------------------------------------------------*/
/*!
* @brief Definition of divider of Tmr2 in decimal, fixed point format.
* @note Definition is only for calculation
*/
#define wTmr_Tmr2Divider_c (12.0)
/*!
* @brief Definition of desired frequency of Tmr2 in Hz and decimal, fixed point format.
*/
#ifndef wTmr_Tmr2DesiredFreq_c
#define wTmr_Tmr2DesiredFreq_c (12000.0)
#endif
/*!
* @brief Definition of max count value of Tmr2 in decimal format. Value is calculated from Sys Clk, Tmr2 freq divider and Tmr2 desired freq.
*/
#define lTmr_Tmr2CntMax_c (lSys_SysClockFreq_c / wTmr_Tmr2Divider_c / wTmr_Tmr2DesiredFreq_c)
/** @name Constant timer frequency definitions
*
* Definition of 8/4/2/1/0.5 Hz frequencies in decimal, fixed point format.
*/
//@{
#define bTmr_8HzFreq_c (8.0)
#define bTmr_4HzFreq_c (4.0)
#define bTmr_2HzFreq_c (2.0)
#define bTmr_1HzFreq_c (1.0)
#define bTmr_0Hz5Freq_c (0.5)
#define bTmr_0Hz25Freq_c (0.25)
//@}
/** @name Constant timer count definitions
*
* Definition of counter values of 8/4/2/1/0.5/0.25 Hz frequencies in decimal, fixed point format. Values are calculated from Tmr2 desired freq and constant freq definitions.
*/
//@{
#define wTmr_8HzCntMax_c (wTmr_Tmr2DesiredFreq_c / bTmr_8HzFreq_c)
#define wTmr_4HzCntMax_c (wTmr_Tmr2DesiredFreq_c / bTmr_4HzFreq_c)
#define wTmr_2HzCntMax_c (wTmr_Tmr2DesiredFreq_c / bTmr_2HzFreq_c)
#define wTmr_1HzCntMax_c (wTmr_Tmr2DesiredFreq_c / bTmr_1HzFreq_c)
#define wTmr_0Hz5CntMax_c (wTmr_Tmr2DesiredFreq_c / bTmr_0Hz5Freq_c)
#define wTmr_0Hz25CntMax_c (wTmr_Tmr2DesiredFreq_c / bTmr_0Hz25Freq_c)
//@}
/** @name External clk select
*
* External clk select definitions of timers.
*/
//@{
#define bTmr_TxXCLK_00_c 0x00
#define bTmr_TxXCLK_01_c 0x01
#define bTmr_TxXCLK_10_c 0x02
#define bTmr_TxXCLK_11_c 0x03
//@}
/** @name Prescaler of timers
*
* Prescaler definitions of TMR2/3.
*/
//@{
#define bTmr_Tmr2One_c M_T2ML
#define bTmr_Tmr2Both_c 0x00
#define bTmr_Tmr3One_c M_T3ML
#define bTmr_Tmr3Both_c 0x00
//@}
/*------------------------------------------------------------------------*/
/* Global structure & enumeration definitions */
/*------------------------------------------------------------------------*/
/*!
* @brief This enumeration contains elements of frequency settings table definitions.
*/
typedef enum _eTmr_ClockSelect
{
eTmr_SysClk_c = 0x00, /**< Timer clock is SysClk (Supported by: Timer 0/1/2/3) */
eTmr_SysClkDiv4_c = 0x10, /**< Timer clock is SysClk/4 (Supported by: Timer 0/1) */
eTmr_SysClkDiv12_c = 0x20, /**< Timer clock is SysClk/12 (Supported by: Timer 0/1/2/3) */
eTmr_SysClkDiv48_c = 0x30, /**< Timer clock is SysClk/48 (Supported by: Timer 0/1) */
} eTmr_ClockSelect;
/*------------------------------------------------------------------------*/
/* Global macros */
/*------------------------------------------------------------------------*/
/** @name Timer 1 macros
*
* Macro interfaces of timer 1 operations.
*/
//@{
#if !(defined SILABS_MCU_F912)
#define mTmr_StartTmr1_7kHz2_24MHz5() CKCON &= 0xF4; CKCON |= 0x08; \
TH1 = 0x96; TMOD &= ~0xF0; \
TMOD |= 0x20; TR1 = 1
#else
// On F912 TH1 needs to set to 0x90. The osc freq seems to be 25.85MHz. Bad parts???
#define mTmr_StartTmr1_7kHz2_24MHz5() CKCON &= 0xF4; CKCON |= 0x08; \
TH1 = 0x90; TMOD &= ~0xF0; \
TMOD |= 0x20; TR1 = 1
#endif
//@}
/** @name Timer 2 macros
*
* Macro interfaces of timer 2 operations.
*/
//@{
#define mTmr_EnableTmr2It() ET2 = 1; TF2H = 0
#define mTmr_DisableTmr2It() ET2 = 0; TF2H = 0
#define mTmr_ClearTmr2It() TF2H = 0
#define mTmr_StopTmr2() TR2 = 0; TF2H = 0
#define mTmr_EnableTmr2() TR2 = 1; TF2H = 0
#define mTmr_StopAndClearTmr2() mTmr_DisableTmr2It(); mTmr_StopTmr2(); TMR2CN = 0u
//@}
/** @name Timer 3 macros
*
* Macro interfaces of timer 3 operations.
*/
//@{
#define mTmr_EnableTmr3It() EIE1 |= 0x80; TMR3CN &= 0x3F
#define mTmr_DisableTmr3It() EIE1 &= (~0x80); TMR3CN &= 0x3F
#define mTmr_ClearTmr3It() TMR3CN &= (~(M_TF3H | M_TF3L))
#define mTmr_StopTmr3() TMR3CN &= (~(M_TF3H | M_TF3L | M_TR3))
#define mTmr_EnableTmr3() TMR3CN |= M_TR3; mTmr_ClearTmr3It()
//@}
/*------------------------------------------------------------------------*/
/* External variables */
/*------------------------------------------------------------------------*/
extern SEGMENT_VARIABLE(wwTmr_Tmr2Periode, UU16, SEG_DATA);
/*------------------------------------------------------------------------*/
/* Function prototypes */
/*------------------------------------------------------------------------*/
void vTmr_StartTmr2(U8 biPrescaler, U16 wiPeriod, U8 biItEnable, U8 biExtClkSel);
#ifdef TIMER_DRIVER_EXTENDED_SUPPORT
BIT gTmr_Tmr2Expired(void);
void vTmr_StartTmr3(U8 biPrescaler, U16 wiPeriod, U8 biItEnable, U8 biExtClkSel);
void vTmr_StartTmr3_phaseConfigure(U8 biPrescaler, U16 wiPeriod, U8 biItEnable, U8 biExtClkSel, U8 biSetItPriorityHigh);
void vTmr_StartTmr3_phaseStart(U16 wiPeriod);
BIT gTmr_Tmr3Expired(void);
#endif
#endif /* TIMER_H_ */
/**
* Copyright 2008 Silicon Laboratories, Inc.
* http://www.silabs.com
*
* @file uart.c
*
* Source File Description:
* @brief TODO
*
* Project Name: EZRADIO SI4X55 EXAMPLES
*
*
* @author Sz. Papp
*
* @date 2012.08.10.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* This software must be used in accordance with the End User License Agreement.
*/
/*****************************************************************************
* Includes
*****************************************************************************/
#include "..\bsp.h"
/*****************************************************************************
* Local variable Declarations
*****************************************************************************/
#ifdef UART_DRIVER_EXTENDED_SUPPORT
volatile SEGMENT_VARIABLE(lUartInternal, tUartData, SEG_XDATA);
#endif
/*****************************************************************************
* Local Functions Definition
*****************************************************************************/
/**
* Simple UART receive function.
*
* @param[out] byte
*
* @return
*
******************************************************************************/
U8 Comm_IF_RecvUART(U8 * byte)
{
#ifdef UART_DRIVER_EXTENDED_SUPPORT
if (lUartInternal.RXReadPosition != lUartInternal.RXWritePosition)
{
*byte = lUartInternal.RXBuffer[lUartInternal.RXReadPosition++];
if (lUartInternal.RXReadPosition >= COMM_IF_UART_RX_BUFFER)
{
lUartInternal.RXReadPosition = 0u;
}
return TRUE;
}
return FALSE;
#else
while (!RI0) ; /* Wait for RX */
RI0 = 0;
*byte = SBUF0;
return TRUE;
#endif
}
/**
* Simple UART send function.
*
* @param byte
*
* @return
*
******************************************************************************/
U8 Comm_IF_SendUART(U8 byte)
{
#ifdef UART_DRIVER_EXTENDED_SUPPORT
/* Check if buffer is full */
if ((lUartInternal.TXReadPosition == lUartInternal.TXWritePosition) && (FALSE == lUartInternal.TXBufferEmpty))
{
return FALSE;
}
/* Write input data byte into buffer */
lUartInternal.TXBuffer[lUartInternal.TXWritePosition++] = byte;
/* Increment pointer */
if (lUartInternal.TXWritePosition >= COMM_IF_UART_TX_BUFFER)
{
lUartInternal.TXWritePosition = 0u;
}
if (TRUE == lUartInternal.TXBufferEmpty)
{
SBUF0 = byte;
}
lUartInternal.TXBufferEmpty = FALSE;
#else
SBUF0 = byte;
while (!TI0) ; /* Wait until TX */
TI0 = 0;
#endif
return TRUE;
}
/**
* Enable and set the UART0 peripheral.
*
* @author Sz. Papp
*
* @note
*
******************************************************************************/
void Comm_IF_EnableUART()
{
/* Enable UART0 in Crossbar */
XBR0 |= 0x01;
/* Timer1 Init for UART baud rate */
/* the default baud rate is 115200bps */
Set115200bps_24MHZ5;
TR1 = 1; /* START Timer1 */
TI0 = 1; /* Transciever ready */
/* UART init */
SCON0 = 0x10;
#ifdef UART_DRIVER_EXTENDED_SUPPORT
/* Enable UART0 IT */
ES0 = TRUE;
lUartInternal.TXBufferEmpty = TRUE;
#endif
}
#ifdef UART_DRIVER_EXTENDED_SUPPORT
/**
* Interrupt handler for UART0 peripheral.
*
* @author Sz. Papp
*
* @note Receive Overrun may occur as it not protected against it yet.
*
*****************************************************************************/
INTERRUPT(UART_ISR, INTERRUPT_UART0)
{
if (TI0)
{
/* Transmit Interrupt */
TI0 = FALSE;
lUartInternal.TXReadPosition++;
if (lUartInternal.TXReadPosition >= COMM_IF_UART_TX_BUFFER)
{
lUartInternal.TXReadPosition = 0u;
}
if (lUartInternal.TXReadPosition == lUartInternal.TXWritePosition)
{
lUartInternal.TXBufferEmpty = TRUE;
}
else
{
SBUF0 = lUartInternal.TXBuffer[lUartInternal.TXReadPosition];
}
}
if (RI0)
{
/* Receive Interrupt */
RI0 = FALSE;
lUartInternal.RXBuffer[lUartInternal.RXWritePosition++] = SBUF0;
if (lUartInternal.RXWritePosition >= COMM_IF_UART_RX_BUFFER)
{
lUartInternal.RXWritePosition = 0u;
}
}
}
#endif
/**
* Copyright 2008 Silicon Laboratories, Inc.
* http://www.silabs.com
*
* @file uart.h
*
* Header File Description:
* @brief TODO
*
* Project Name: EZRADIO SI4x55 EXAMPLES
*
*
* @author Sz. Papp
*
* @date 2012.08.10.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* This software must be used in accordance with the End User License Agreement.
*/
#ifndef UART_H_
#define UART_H_
/*****************************************************************************
* Global Macros & Definitions
*****************************************************************************/
/*! UART RX Buffer size */
#ifndef COMM_IF_UART_RX_BUFFER
#define COMM_IF_UART_RX_BUFFER 64u
#endif
/*! UART TX Buffer size */
#ifndef COMM_IF_UART_TX_BUFFER
#define COMM_IF_UART_TX_BUFFER 64u
#endif
/*! Macro to set the UART baud rate to 115200bps (with 30MHz XTAL) */
#if !(defined SILABS_MCU_F912)
#define Set115200bps_24MHZ5 CKCON &= 0xF4; CKCON |= 0x08; \
TH1 = 0x96; TMOD &= ~0xF0; \
TMOD |= 0x20
#else
// On F912 TH1 needs to set to 0x90. The osc freq seems to be 25.85MHz. Bad parts???
#define Set115200bps_24MHZ5 CKCON &= 0xF4; CKCON |= 0x08; \
TH1 = 0x90; TMOD &= ~0xF0; \
TMOD |= 0x20
#endif
/*****************************************************************************
* Global Enums & Typedefs
*****************************************************************************/
typedef struct
{
U8 TXWritePosition;
U8 TXReadPosition;
U8 TXBufferEmpty;
U8 RXWritePosition;
U8 RXReadPosition;
U8 RXBuffer[COMM_IF_UART_RX_BUFFER];
U8 TXBuffer[COMM_IF_UART_TX_BUFFER];
} tUartData;
/*****************************************************************************
* Global Function Declarations
*****************************************************************************/
U8 Comm_IF_RecvUART(U8 *);
U8 Comm_IF_SendUART(U8);
void Comm_IF_EnableUART(void);
/*****************************************************************************
* Interrupt function prototype
*****************************************************************************/
#ifdef UART_DRIVER_EXTENDED_SUPPORT
INTERRUPT_PROTO(UART_ISR, INTERRUPT_UART0);
#endif
#endif /* UART_H_ */