📄 hal.c
字号:
/*----------------------------------------------------------------------------*//** \brief This function reads the value of a specific subregister. * * \see Look at the at86rf230_registermap.h file for register and subregister * definitions. * * \param address Main register's address. * \param mask Bit mask of the subregister. * \param position Bit position of the subregister * \retval Value of the read subregister. */uint8_thal_subregister_read(uint8_t address, uint8_t mask, uint8_t position){ /* Read current register value and mask out subregister. */ uint8_t register_value = hal_register_read(address); register_value &= mask; register_value >>= position; /* Align subregister value. */ return register_value;}/*----------------------------------------------------------------------------*//** \brief This function writes a new value to one of the radio transceiver's * subregisters. * * \see Look at the at86rf230_registermap.h file for register and subregister * definitions. * * \param address Main register's address. * \param mask Bit mask of the subregister. * \param position Bit position of the subregister * \param value Value to write into the subregister. */voidhal_subregister_write(uint8_t address, uint8_t mask, uint8_t position, uint8_t value){ /* Read current register value and mask area outside the subregister. */ uint8_t register_value = hal_register_read(address); register_value &= ~mask; /* Start preparing the new subregister value. shift in place and mask. */ value <<= position; value &= mask; value |= register_value; /* Set the new subregister value. */ /* Write the modified register value. */ hal_register_write(address, value);}/*----------------------------------------------------------------------------*//** \brief This function will upload a frame from the radio transceiver's frame * buffer. * * If the frame currently available in the radio transceiver's frame buffer * is out of the defined bounds. Then the frame length, lqi value and crc * be set to zero. This is done to indicate an error. * * \param rx_frame Pointer to the data structure where the frame is stored. * \param rx_callback Pointer to callback function for receiving one byte at a time. */voidhal_frame_read(hal_rx_frame_t *rx_frame, rx_callback_t rx_callback){ uint8_t *rx_data=0; /* check that we have either valid frame pointer or callback pointer */ if (!rx_frame && !rx_callback) return; AVR_ENTER_CRITICAL_REGION(); HAL_SS_LOW(); /*Send frame read command.*/ SPDR = HAL_TRX_CMD_FR; while ((SPSR & (1 << SPIF)) == 0) {;} uint8_t frame_length = SPDR; /*Read frame length.*/ SPDR = frame_length; while ((SPSR & (1 << SPIF)) == 0) {;} frame_length = SPDR; /*Check for correct frame length.*/ if ((frame_length >= HAL_MIN_FRAME_LENGTH) && (frame_length <= HAL_MAX_FRAME_LENGTH)){ uint16_t crc = 0; if (rx_frame){ rx_data = (rx_frame->data); rx_frame->length = frame_length; /* Store frame length. */ } else { rx_callback(frame_length); } /*Upload frame buffer to data pointer. Calculate CRC.*/ SPDR = frame_length; while ((SPSR & (1 << SPIF)) == 0) {;} do{ uint8_t tempData = SPDR; SPDR = 0; /* dummy write */ if (rx_frame){ *rx_data++ = tempData; } else { rx_callback(tempData); } crc = _crc_ccitt_update(crc, tempData); while ((SPSR & (1 << SPIF)) == 0) {;} } while (--frame_length > 0); /*Read LQI value for this frame.*/ if (rx_frame){ rx_frame->lqi = SPDR; } else { rx_callback(SPDR); } HAL_SS_HIGH(); /*Check calculated crc, and set crc field in hal_rx_frame_t accordingly.*/ if (rx_frame){ rx_frame->crc = (crc == HAL_CALCULATED_CRC_OK); } else { rx_callback(crc != HAL_CALCULATED_CRC_OK); } } else { HAL_SS_HIGH(); if (rx_frame){ rx_frame->length = 0; rx_frame->lqi = 0; rx_frame->crc = false; } } AVR_LEAVE_CRITICAL_REGION();}/*----------------------------------------------------------------------------*//** \brief This function will download a frame to the radio transceiver's frame * buffer. * * \param write_buffer Pointer to data that is to be written to frame buffer. * \param length Length of data. The maximum length is 127 bytes. */voidhal_frame_write(uint8_t *write_buffer, uint8_t length){ length &= HAL_TRX_CMD_RADDRM; /* Truncate length to maximum frame length. */ AVR_ENTER_CRITICAL_REGION(); HAL_SS_LOW(); /* Initiate the SPI transaction. */ /*SEND FRAME WRITE COMMAND AND FRAME LENGTH.*/ SPDR = HAL_TRX_CMD_FW; while ((SPSR & (1 << SPIF)) == 0) {;} uint8_t dummy_read = SPDR; SPDR = length; while ((SPSR & (1 << SPIF)) == 0) {;} dummy_read = SPDR; /* Download to the Frame Buffer. */ do{ SPDR = *write_buffer++; --length; while ((SPSR & (1 << SPIF)) == 0) {;} dummy_read = SPDR; } while (length > 0); HAL_SS_HIGH(); /* Terminate SPI transaction. */ AVR_LEAVE_CRITICAL_REGION();}/*----------------------------------------------------------------------------*//** \brief Read SRAM * * This function reads from the SRAM of the radio transceiver. * * \param address Address in the TRX's SRAM where the read burst should start * \param length Length of the read burst * \param data Pointer to buffer where data is stored. */voidhal_sram_read(uint8_t address, uint8_t length, uint8_t *data){ AVR_ENTER_CRITICAL_REGION(); HAL_SS_LOW(); /* Initiate the SPI transaction. */ /*Send SRAM read command.*/ SPDR = HAL_TRX_CMD_SR; while ((SPSR & (1 << SPIF)) == 0) {;} uint8_t dummy_read = SPDR; /*Send address where to start reading.*/ SPDR = address; while ((SPSR & (1 << SPIF)) == 0) {;} dummy_read = SPDR; /*Upload the chosen memory area.*/ do{ SPDR = HAL_DUMMY_READ; while ((SPSR & (1 << SPIF)) == 0) {;} *data++ = SPDR; } while (--length > 0); HAL_SS_HIGH(); AVR_LEAVE_CRITICAL_REGION();}/*----------------------------------------------------------------------------*//** \brief Write SRAM * * This function writes into the SRAM of the radio transceiver. * * \param address Address in the TRX's SRAM where the write burst should start * \param length Length of the write burst * \param data Pointer to an array of bytes that should be written */voidhal_sram_write(uint8_t address, uint8_t length, uint8_t *data){ AVR_ENTER_CRITICAL_REGION(); HAL_SS_LOW(); /*Send SRAM write command.*/ SPDR = HAL_TRX_CMD_SW; while ((SPSR & (1 << SPIF)) == 0) {;} uint8_t dummy_read = SPDR; /*Send address where to start writing to.*/ SPDR = address; while ((SPSR & (1 << SPIF)) == 0) {;} dummy_read = SPDR; /*Upload the chosen memory area.*/ do{ SPDR = *data++; while ((SPSR & (1 << SPIF)) == 0) {;} dummy_read = SPDR; } while (--length > 0); HAL_SS_HIGH(); AVR_LEAVE_CRITICAL_REGION();}/*----------------------------------------------------------------------------*//* This #if compile switch is used to provide a "standard" function body for the *//* doxygen documentation. */#if defined(DOXYGEN)/** \brief ISR for the radio IRQ line, triggered by the input capture. * This is the interrupt service routine for timer1.ICIE1 input capture. * It is triggered of a rising edge on the radio transceivers IRQ line. */void RADIO_VECT(void);#else /* !DOXYGEN */ISR(RADIO_VECT){ /*The following code reads the current system time. This is done by first reading the hal_system_time and then adding the 16 LSB directly from the TCNT1 register. */ uint32_t isr_timestamp = hal_system_time; isr_timestamp <<= 16; isr_timestamp |= TCNT1; /*Read Interrupt source.*/ HAL_SS_LOW(); /*Send Register address and read register content.*/ SPDR = RG_IRQ_STATUS | HAL_TRX_CMD_RR; /* This is the second part of the convertion of system time to a 16 us time base. The division is moved here so we can spend less time waiting for SPI data. */ isr_timestamp /= HAL_US_PER_SYMBOL; /* Divide so that we get time in 16us resolution. */ isr_timestamp &= HAL_SYMBOL_MASK; while ((SPSR & (1 << SPIF)) == 0) {;} uint8_t interrupt_source = SPDR; /* The interrupt variable is used as a dummy read. */ SPDR = interrupt_source; while ((SPSR & (1 << SPIF)) == 0) {;} interrupt_source = SPDR; /* The interrupt source is read. */ HAL_SS_HIGH(); /*Handle the incomming interrupt. Prioritized.*/ if ((interrupt_source & HAL_RX_START_MASK)){ if(rx_start_callback != NULL){ /* Read Frame length and call rx_start callback. */ HAL_SS_LOW(); SPDR = HAL_TRX_CMD_FR; while ((SPSR & (1 << SPIF)) == 0) {;} uint8_t frame_length = SPDR; SPDR = frame_length; /* frame_length used for dummy data */ while ((SPSR & (1 << SPIF)) == 0) {;} frame_length = SPDR; HAL_SS_HIGH(); rx_start_callback(isr_timestamp, frame_length); } } else if (interrupt_source & HAL_TRX_END_MASK){ if(trx_end_callback != NULL){ trx_end_callback(isr_timestamp); } } else if (interrupt_source & HAL_TRX_UR_MASK){ ; } else if (interrupt_source & HAL_PLL_UNLOCK_MASK){ ; } else if (interrupt_source & HAL_PLL_LOCK_MASK){ hal_pll_lock_flag++; ; } else if (interrupt_source & HAL_BAT_LOW_MASK){ /* Disable BAT_LOW interrupt to prevent endless interrupts. The interrupt */ /* will continously be asserted while the supply voltage is less than the */ /* user-defined voltage threshold. */ uint8_t trx_isr_mask = hal_register_read(RG_IRQ_MASK); trx_isr_mask &= ~HAL_BAT_LOW_MASK; hal_register_write(RG_IRQ_MASK, trx_isr_mask); hal_bat_low_flag++; /* Increment BAT_LOW flag. */ } else { ; }}# endif /* defined(DOXYGEN) *//*----------------------------------------------------------------------------*//* This #if compile switch is used to provide a "standard" function body for the *//* doxygen documentation. */#if defined(DOXYGEN)/** \brief Timer Overflow ISR * This is the interrupt service routine for timer1 overflow. */void TIMER1_OVF_vect(void);#else /* !DOXYGEN */ISR(TIMER1_OVF_vect){ hal_system_time++;}#endif/** @} *//** @} *//*EOF*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -