774 lines
23 KiB
C
774 lines
23 KiB
C
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#include "gd32e23x.h"
|
|
#include "systick.h"
|
|
#include "soniclib.h"
|
|
#include "chirp_smartsonic.h"
|
|
|
|
#include "board_init.h"
|
|
#include "chirp_board_config.h"
|
|
#include "i2c.h"
|
|
|
|
|
|
|
|
static uint8_t chirp_i2c_addrs[] = CHIRP_I2C_ADDRS;
|
|
static uint8_t chirp_i2c_buses[] = CHIRP_I2C_BUSES;
|
|
|
|
|
|
/* chirp sensor group pointer */
|
|
ch_group_t *sensor_group_ptr;
|
|
|
|
/* Callback function pointers */
|
|
static ch_timer_callback_t periodic_timer_callback_ptr = NULL;
|
|
|
|
static uint16_t periodic_timer_interval_ms;
|
|
|
|
static uint16_t ultrasound_timer_period_in_tick = 0xFFFF;
|
|
static uint16_t ultrasound_prev_period_end_in_tick;
|
|
|
|
/* Counter used to decimate call to ultrasound timer callback from TC0 ISR in case decimation
|
|
factor is != 1 */
|
|
static uint8_t decimation_counter = 0;
|
|
|
|
|
|
#ifdef CHIRP_ADC_NONE
|
|
static void measure_idd(uint16_t nb_measure){
|
|
__NOP();
|
|
}
|
|
#elif
|
|
static void measure_idd(uint16_t nb_measure){
|
|
__NOP();
|
|
}
|
|
#endif
|
|
|
|
#ifdef CHIRP_ADC_NONE
|
|
static void measure_power(void){
|
|
__NOP();
|
|
}
|
|
#elif
|
|
static void measure_power(void){
|
|
uint32_t sensors_current;
|
|
|
|
sensors_current = measure_idd(SENSORS_CURRENT_NB_MEASURE);
|
|
printf("Chirp Sensor Idd is %ld uA \n\n", sensors_current);
|
|
}
|
|
#endif
|
|
|
|
/*!
|
|
\brief Probe I2C bus to find connected sensor(s)
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval none
|
|
\note 1. Pull-High PROG
|
|
2. Read Register From PROG Mode 0x00
|
|
3. Verify Register Value.
|
|
4. Pull-Low PROG
|
|
*/
|
|
static void find_sensors(void)
|
|
{
|
|
uint8_t sig_bytes[2];
|
|
uint8_t i;
|
|
|
|
/* config RST GPIO : --Output--High-- */
|
|
gpio_mode_set(CHIRP_PIN_RST_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, CHIRP_PIN_RST_PIN);
|
|
gpio_output_options_set(CHIRP_PIN_RST_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, CHIRP_PIN_RST_PIN);
|
|
gpio_bit_set(CHIRP_PIN_RST_PORT, CHIRP_PIN_RST_PIN);
|
|
|
|
/* config PROG GPIO : --Output--Low-- */
|
|
gpio_mode_set(CHIRP_PIN_PROG_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, CHIRP_PIN_PROG_PIN);
|
|
gpio_output_options_set(CHIRP_PIN_PROG_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, CHIRP_PIN_PROG_PIN);
|
|
gpio_bit_reset(CHIRP_PIN_PROG_PORT, CHIRP_PIN_PROG_PIN);
|
|
|
|
/* check sensor */
|
|
/* pull PROG Pin to high */
|
|
gpio_bit_set(CHIRP_PIN_PROG_PORT, CHIRP_PIN_PROG_PIN);
|
|
i2c_master_initialize1();
|
|
sig_bytes[0] = 0;
|
|
sig_bytes[1] = 0;
|
|
|
|
i2c_master_read_register1(CH_I2C_ADDR_PROG, 0x00, 2, sig_bytes);
|
|
|
|
printf("Chirp Sensor ");
|
|
if ((sig_bytes[0] = CH_SIG_BYTE_0) && (sig_bytes[1] = CH_SIG_BYTE_1)){
|
|
printf("found!\n");
|
|
} else {
|
|
printf("not found!\n");
|
|
}
|
|
gpio_bit_reset(CHIRP_PIN_PROG_PORT, CHIRP_PIN_PROG_PIN);
|
|
}
|
|
|
|
#ifdef CHIRP_ADC_NONE
|
|
static void ADC0_init(void){
|
|
__NOP();
|
|
}
|
|
#elif
|
|
static void ADC0_init(void){
|
|
adc_enable();
|
|
}
|
|
#endif
|
|
|
|
/*!
|
|
\brief Initialize INT Pin EXTI
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval none
|
|
*/
|
|
void ext_int_init(void)
|
|
{
|
|
/* enable clock */
|
|
rcu_periph_clock_enable(RCU_GPIOA | RCU_CFGCMP);
|
|
// Configure PIOs as input pins & Enable pull-downs on the INT pins
|
|
gpio_mode_set(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, GPIO_PIN_7);
|
|
/* enable and set INT EXTI interrupt priority */
|
|
nvic_irq_enable(EXTI4_15_IRQn, 2U);
|
|
/* connect key EXTI line to key GPIO pin */
|
|
syscfg_exti_line_config(EXTI_SOURCE_GPIOA, EXTI_SOURCE_PIN7);
|
|
/* configure key EXTI line Initialize INT interrupt handler, interrupt on rising edge. */
|
|
exti_init(EXTI_7, EXTI_INTERRUPT, EXTI_TRIG_RISING);
|
|
exti_interrupt_flag_clear(EXTI_7);
|
|
/* Disable all CHx01 interrupts */
|
|
exti_interrupt_disable(EXTI_7);
|
|
}
|
|
|
|
|
|
/*!
|
|
\brief Initialize board HardWare
|
|
\param[in] none
|
|
\param[out] none
|
|
\retval none
|
|
\note This function performs all neceassary initialization on the board.
|
|
*/
|
|
void chbsp_board_init(ch_group_t *grp_ptr) {
|
|
/* make local copy of group pointer */
|
|
sensor_group_ptr = grp_ptr;
|
|
|
|
/* Initialize group descriptor */
|
|
grp_ptr->num_ports = CHIRP_MAX_NUM_SENSORS;
|
|
grp_ptr->num_i2c_buses = CHIRP_NUM_I2C_BUSES;
|
|
grp_ptr->rtc_cal_pulse_ms = CHBSP_RTC_CAL_PULSE_MS;
|
|
|
|
board_init_I2C();
|
|
configure_console();
|
|
ADC0_init();
|
|
ext_int_init();
|
|
/* Probe I2C bus to find connected sensor(s) */
|
|
find_sensors();
|
|
measure_power();
|
|
indicate_alive();
|
|
}
|
|
|
|
/*!
|
|
* \brief Assert the reset pin
|
|
*
|
|
* This function drives the sensor reset pin low.
|
|
*/
|
|
void chbsp_reset_assert(void) {
|
|
|
|
gpio_bit_reset(CHIRP_PIN_RST_PORT, CHIRP_PIN_RST_PIN); //reset=L
|
|
}
|
|
|
|
/*!
|
|
* \brief Deassert the reset pin
|
|
*
|
|
* This function drives the sensor reset pin high.
|
|
*/
|
|
void chbsp_reset_release(void) {
|
|
|
|
gpio_bit_set(CHIRP_PIN_RST_PORT, CHIRP_PIN_RST_PIN); //reset=H
|
|
}
|
|
|
|
/*!
|
|
* \brief Assert the PROG pin
|
|
*
|
|
* \param dev_ptr pointer to the ch_dev_t config structure for a sensor
|
|
*
|
|
* This function drives the sensor PROG pin high on the specified port.
|
|
*/
|
|
void chbsp_program_enable(ch_dev_t *dev_ptr) {
|
|
uint8_t dev_num = ch_get_dev_num(dev_ptr);
|
|
gpio_bit_set(CHIRP_PIN_PROG_PORT, CHIRP_PIN_PROG_PIN); //PROG_0=H
|
|
|
|
}
|
|
|
|
/*!
|
|
* \brief Deassert the PROG pin
|
|
*
|
|
* \param dev_ptr pointer to the ch_dev_t config structure for a sensor
|
|
*
|
|
* This function drives the sensor PROG pin low on the specified port.
|
|
*/
|
|
void chbsp_program_disable(ch_dev_t *dev_ptr) {
|
|
uint8_t dev_num = ch_get_dev_num(dev_ptr);
|
|
gpio_bit_reset(CHIRP_PIN_PROG_PORT, CHIRP_PIN_PROG_PIN); //PROG_0=L
|
|
}
|
|
|
|
/*!
|
|
* \brief Configure the Chirp sensor INT pin as an output for one sensor.
|
|
*
|
|
* \param dev_ptr pointer to the ch_dev_t config structure for a sensor
|
|
*
|
|
* This function configures the Chirp sensor INT pin as an output (from the perspective
|
|
* of the host system).
|
|
*/
|
|
void chbsp_set_io_dir_out(ch_dev_t *dev_ptr) {
|
|
uint8_t dev_num = ch_get_dev_num(dev_ptr);
|
|
gpio_mode_set(CHIRP_PIN_INT_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, CHIRP_PIN_INT_PIN);
|
|
gpio_output_options_set(CHIRP_PIN_INT_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, CHIRP_PIN_INT_PIN);
|
|
}
|
|
|
|
|
|
/*!
|
|
* \brief Configure the Chirp sensor INT pin as an input for one sensor.
|
|
*
|
|
* \param dev_ptr pointer to the ch_dev_t config structure for a sensor
|
|
*
|
|
* This function configures the Chirp sensor INT pin as an input (from the perspective of
|
|
* the host system).
|
|
*/
|
|
void chbsp_set_io_dir_in(ch_dev_t *dev_ptr) {
|
|
uint8_t dev_num = ch_get_dev_num(dev_ptr);
|
|
gpio_mode_set(CHIRP_PIN_INT_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, CHIRP_PIN_INT_PIN);
|
|
}
|
|
|
|
|
|
/*!
|
|
* \brief Configure the Chirp sensor INT pins as outputs for a group of sensors
|
|
*
|
|
* \param grp_ptr pointer to the ch_group_t config structure for a group of sensors
|
|
*
|
|
* This function configures each Chirp sensor's INT pin as an output (from the perspective
|
|
* of the host system).
|
|
*/
|
|
void chbsp_group_set_io_dir_out(ch_group_t *grp_ptr) {
|
|
uint8_t dev_num;
|
|
|
|
for (dev_num = 0; dev_num < ch_get_num_ports(grp_ptr); dev_num++)
|
|
{
|
|
ch_dev_t *dev_ptr = ch_get_dev_ptr(grp_ptr, dev_num);
|
|
|
|
if (ch_sensor_is_connected(dev_ptr)){
|
|
gpio_mode_set(CHIRP_PIN_INT_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, CHIRP_PIN_INT_PIN);
|
|
gpio_output_options_set(CHIRP_PIN_INT_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, CHIRP_PIN_INT_PIN);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*!
|
|
* \brief Configure the Chirp sensor INT pins as inputs for a group of sensors
|
|
*
|
|
* \param grp_ptr pointer to the ch_group_t config structure for a group of sensors
|
|
*
|
|
* \note This function assumes a bidirectional level shifter is interfacing the ICs.
|
|
*/
|
|
void chbsp_group_set_io_dir_in(ch_group_t *grp_ptr) {
|
|
uint8_t dev_num;
|
|
|
|
for (dev_num = 0; dev_num < ch_get_num_ports(grp_ptr); dev_num++) {
|
|
ch_dev_t *dev_ptr = ch_get_dev_ptr(grp_ptr, dev_num);
|
|
|
|
if (ch_sensor_is_connected(dev_ptr)) {
|
|
gpio_mode_set(CHIRP_PIN_INT_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, CHIRP_PIN_INT_PIN);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*!
|
|
* \brief Initialize the I/O pins.
|
|
*
|
|
* \param grp_ptr pointer to the ch_group_t config structure for a group of sensors
|
|
*
|
|
* Configure reset and program pins as outputs. Assert reset and program. Configure
|
|
* sensor INT pin as input.
|
|
*/
|
|
void chbsp_group_pin_init(ch_group_t *grp_ptr) {
|
|
uint8_t dev_num;
|
|
uint8_t port_num;
|
|
|
|
gpio_mode_set(CHIRP_PIN_PROG_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, CHIRP_PIN_PROG_PIN);
|
|
gpio_output_options_set(CHIRP_PIN_PROG_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, CHIRP_PIN_PROG_PIN);
|
|
gpio_bit_reset(CHIRP_PIN_PROG_PORT, CHIRP_PIN_PROG_PIN);
|
|
|
|
// ioport_set_pin_dir(CHIRP_RST, IOPORT_DIR_OUTPUT); //reset=output
|
|
gpio_mode_set(CHIRP_PIN_RST_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, CHIRP_PIN_RST_PIN);
|
|
gpio_output_options_set(CHIRP_PIN_RST_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, CHIRP_PIN_RST_PIN);
|
|
chbsp_reset_assert();
|
|
|
|
|
|
for (dev_num = 0; dev_num < grp_ptr->num_ports; dev_num++) {
|
|
ch_dev_t *dev_ptr = ch_get_dev_ptr(grp_ptr, dev_num);
|
|
chbsp_program_enable(dev_ptr);
|
|
}
|
|
|
|
/* Initialize IO pins */
|
|
chbsp_group_set_io_dir_in(grp_ptr);
|
|
|
|
/* Enable the peripheral clock for the MAG extension board interrupt pin. */
|
|
rcu_periph_clock_enable(CHIRP_PIN_INT_CLK);
|
|
rcu_periph_clock_enable(RCU_CFGCMP);
|
|
|
|
/* Configure PIOs as input pins. */
|
|
for(port_num = 0; port_num < grp_ptr->num_ports; port_num++ ) {
|
|
gpio_mode_set(CHIRP_PIN_INT_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, CHIRP_PIN_INT_PIN);
|
|
}
|
|
nvic_irq_enable(EXTI4_15_IRQn, 2U);
|
|
syscfg_exti_line_config(CHIRP_EXTI_INT_PORT, CHIRP_EXTI_INT_PIN);
|
|
exti_init(CHIRP_EXTI_INT_LINE, EXTI_INTERRUPT, EXTI_TRIG_RISING);
|
|
exti_interrupt_flag_clear(CHIRP_EXTI_INT_LINE);
|
|
}
|
|
|
|
|
|
/*!
|
|
* \brief Set the INT pins low for a group of sensors.
|
|
*
|
|
* \param grp_ptr pointer to the ch_group_t config structure for a group of sensors
|
|
*
|
|
* This function drives the INT line low for each sensor in the group.
|
|
*/
|
|
void chbsp_group_io_clear(ch_group_t *grp_ptr) {
|
|
// ioport_port_mask_t mask = 0;
|
|
uint8_t dev_num;
|
|
|
|
for (dev_num = 0; dev_num < ch_get_num_ports(grp_ptr); dev_num++) {
|
|
ch_dev_t *dev_ptr = ch_get_dev_ptr(grp_ptr, dev_num);
|
|
|
|
if (ch_sensor_is_connected(dev_ptr)) {
|
|
gpio_bit_reset(CHIRP_PIN_INT_PORT, CHIRP_PIN_INT_PIN); //INT_0=L
|
|
}
|
|
}
|
|
}
|
|
|
|
/*!
|
|
* \brief Set the INT pins high for a group of sensors.
|
|
*
|
|
* \param grp_ptr pointer to the ch_group_t config structure for a group of sensors
|
|
*
|
|
* This function drives the INT line high for each sensor in the group.
|
|
*/
|
|
void chbsp_group_io_set(ch_group_t *grp_ptr) {
|
|
ch_dev_t *dev_ptr = ch_get_dev_ptr(grp_ptr, 0);
|
|
if (ch_sensor_is_connected(dev_ptr))
|
|
{
|
|
gpio_bit_set(CHIRP_PIN_INT_PORT, CHIRP_PIN_INT_PIN);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
* \brief Delay for specified number of microseconds
|
|
*
|
|
* \param us number of microseconds to delay before returning
|
|
*
|
|
* This function waits for the specified number of microseconds before returning to
|
|
* the caller.
|
|
*/
|
|
void chbsp_delay_us(uint32_t us) {
|
|
|
|
delay_us(us);
|
|
}
|
|
|
|
/*!
|
|
* \brief Delay for specified number of milliseconds.
|
|
*
|
|
* \param ms number of milliseconds to delay before returning
|
|
*
|
|
* This function waits for the specified number of milliseconds before returning to
|
|
* the caller.
|
|
*/
|
|
void chbsp_delay_ms(uint32_t ms) {
|
|
|
|
delay_ms(ms);
|
|
}
|
|
|
|
/*!
|
|
* \brief Initialize the host's I2C hardware.
|
|
*
|
|
* \return 0 if successful, 1 on error
|
|
*
|
|
* This function performs general I2C initialization on the host system.
|
|
*/
|
|
int chbsp_i2c_init(void) {
|
|
|
|
i2c_master_init();
|
|
return 0;
|
|
|
|
}
|
|
|
|
/*!
|
|
* \brief Return I2C information for a sensor port on the board.
|
|
*
|
|
* \param grp_ptr pointer to the ch_group_t config structure for a group of sensors
|
|
* \param dev_num device number within sensor group
|
|
* \param info_ptr pointer to structure to be filled with I2C config values
|
|
*
|
|
* \return 0 if successful, 1 if error
|
|
*
|
|
* This function returns I2C values in the ch_i2c_info_t structure specified by \a info_ptr.
|
|
* The structure includes three fields.
|
|
* - The \a address field contains the I2C address for the sensor.
|
|
* - The \a bus_num field contains the I2C bus number (index).
|
|
* - The \a drv_flags field contains various bit flags through which the BSP can inform
|
|
* SonicLib driver functions to perform specific actions during I2C I/O operations.
|
|
*/
|
|
uint8_t chbsp_i2c_get_info(ch_group_t __attribute__((unused)) *grp_ptr, uint8_t io_index, ch_i2c_info_t *info_ptr) {
|
|
uint8_t ret_val = 1;
|
|
|
|
if (io_index <= CHBSP_MAX_DEVICES) {
|
|
// info_ptr->address = chirp_i2c_addrs[io_index];
|
|
// info_ptr->bus_num = chirp_i2c_buses[io_index];
|
|
|
|
info_ptr->address = chirp_i2c_addrs[io_index];
|
|
info_ptr->bus_num = chirp_i2c_buses[io_index];
|
|
info_ptr->drv_flags = 0; // no special I2C handling by SonicLib driver is needed
|
|
|
|
ret_val = 0;
|
|
}
|
|
return ret_val;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
* \brief Write bytes to an I2C slave.
|
|
*
|
|
* \param dev_ptr pointer to the ch_dev_t config structure for a sensor
|
|
* \param data data to be transmitted
|
|
* \param num_bytes length of data to be transmitted
|
|
*
|
|
* \return 0 if successful, 1 on error or NACK
|
|
*
|
|
* This function writes one or more bytes of data to an I2C slave device.
|
|
* The I2C interface must have already been initialized using \a chbsp_i2c_init().
|
|
*/
|
|
int chbsp_i2c_write(ch_dev_t *dev_ptr, uint8_t *data, uint16_t num_bytes) {
|
|
int error = 0;
|
|
|
|
if (dev_ptr->i2c_bus_index == 0) {
|
|
error = i2c_master_write_register1_raw(dev_ptr->i2c_address, num_bytes, data); //I2C bus 0 (TWI1)
|
|
} else {
|
|
// error = i2c_master_write_register3_raw(dev_ptr->i2c_address, num_bytes, data); //I2C bus 1 (TWI3)
|
|
printf("err 'chbsp_i2c_write' on chbsp, no TWI3");
|
|
}
|
|
return error;
|
|
}
|
|
|
|
/*!
|
|
* \brief Write bytes to an I2C slave using memory addressing.
|
|
*
|
|
* \param dev_ptr pointer to the ch_dev_t config structure for a sensor
|
|
* \param mem_addr internal memory or register address within device
|
|
* \param data data to be transmitted
|
|
* \param num_bytes length of data to be transmitted
|
|
*
|
|
* \return 0 if successful, 1 on error or NACK
|
|
*
|
|
* This function writes one or more bytes of data to an I2C slave device using an internal
|
|
* memory or register address. The remote device will write \a num_bytes bytes of
|
|
* data starting at internal memory/register address \a mem_addr.
|
|
* The I2C interface must have already been initialized using \a chbsp_i2c_init().
|
|
*/
|
|
int chbsp_i2c_mem_write(ch_dev_t *dev_ptr, uint16_t mem_addr, uint8_t *data, uint16_t num_bytes) {
|
|
int error=0;
|
|
if (dev_ptr->i2c_bus_index == 0) {
|
|
// I2C bus 0 (TWI1)
|
|
error = i2c_master_write_register1(dev_ptr->i2c_address, mem_addr, num_bytes, data);
|
|
|
|
} else if (dev_ptr->i2c_bus_index == 1) {
|
|
// I2C bus 1 (TWI3)
|
|
printf("err 'chbsp_i2c_mem_write' on chbsp, no TWI3");
|
|
}
|
|
return error;
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
* \brief Read bytes from an I2C slave.
|
|
*
|
|
* \param dev_ptr pointer to the ch_dev_t config structure for a sensor
|
|
* \param data pointer to receive data buffer
|
|
* \param num_bytes number of bytes to read
|
|
*
|
|
* \return 0 if successful, 1 on error or NACK
|
|
*
|
|
* This function reads the specified number of bytes from an I2C slave device.
|
|
* The I2C interface must have already been initialized using \a chbsp_i2c_init().
|
|
*/
|
|
int chbsp_i2c_read(ch_dev_t *dev_ptr, uint8_t *data, uint16_t num_bytes) {
|
|
int error = 1; // default is error return
|
|
uint8_t i2c_addr = ch_get_i2c_address(dev_ptr);
|
|
uint8_t bus_num = ch_get_i2c_bus(dev_ptr);
|
|
|
|
if (bus_num == 0) {
|
|
// I2C bus 0 (TWI1)
|
|
error = i2c_master_read_register1_raw(i2c_addr, num_bytes, data);
|
|
|
|
} else if (bus_num == 1) {
|
|
// I2C bus 1 (TWI3)
|
|
error = i2c_master_read_register3_raw(i2c_addr, num_bytes, data);
|
|
}
|
|
return error;
|
|
}
|
|
|
|
/*!
|
|
* \brief Read bytes from an I2C slave using memory addressing.
|
|
*
|
|
* \param dev_ptr pointer to the ch_dev_t config structure for a sensor
|
|
* \param mem_addr internal memory or register address within device
|
|
* \param data pointer to receive data buffer
|
|
* \param num_bytes number of bytes to read
|
|
*
|
|
* \return 0 if successful, 1 on error or NACK
|
|
*
|
|
* This function reads the specified number of bytes from an I2C slave device, using
|
|
* an internal memory or register address. The remote device will return \a num_bytes bytes
|
|
* starting at internal memory/register address \a mem_addr.
|
|
*
|
|
* The I2C interface must have already been initialized using \a chbsp_i2c_init().
|
|
*/
|
|
int chbsp_i2c_mem_read(ch_dev_t *dev_ptr, uint16_t mem_addr, uint8_t *data, uint16_t num_bytes) {
|
|
int error = 1; // default is error return
|
|
uint8_t i2c_addr = ch_get_i2c_address(dev_ptr);
|
|
uint8_t bus_num = ch_get_i2c_bus(dev_ptr);
|
|
|
|
if (bus_num == 0) {
|
|
// I2C bus 0 (TWI1)
|
|
error = i2c_master_read_register1(i2c_addr, mem_addr, num_bytes, data);
|
|
|
|
} else if (bus_num == 1) {
|
|
// I2C bus 1 (TWI3)
|
|
error = i2c_master_read_register3(i2c_addr, mem_addr, num_bytes, data);
|
|
#ifdef DEBUG_VERBOES
|
|
printf("\n err 'chbsp_i2c_mem_read' on chbsp_chirp_gd32e230f4, no TWI3 \n");
|
|
#endif
|
|
}
|
|
return error;
|
|
}
|
|
|
|
/*!
|
|
* \brief Reset I2C bus associated with device.
|
|
*
|
|
* \param dev_ptr pointer to the ch_dev_t config structure for a sensor
|
|
*
|
|
* This function performs a reset of the I2C interface for the specified device.
|
|
*/
|
|
void chbsp_i2c_reset(ch_dev_t * dev_ptr) {
|
|
uint8_t bus_num = ch_get_i2c_bus(dev_ptr);
|
|
|
|
if (bus_num == 0) { // I2C bus 0 (TWI1)
|
|
i2c_master_initialize1();
|
|
} else if (bus_num == 1) { // I2C bus 1 (TWI3)
|
|
i2c_master_initialize3();
|
|
}
|
|
}
|
|
|
|
/*!
|
|
* \brief Initialize periodic timer.
|
|
*
|
|
* \param interval_ms timer interval, in milliseconds
|
|
* \param callback_func_ptr address of routine to be called every time the timer expires
|
|
*
|
|
* \return 0 if successful, 1 if error
|
|
*
|
|
* This function initializes a periodic timer on the board. The timer is programmed
|
|
* to generate an interrupt after every \a interval_ms milliseconds.
|
|
*
|
|
* The \a callback_func_ptr parameter specifies a callback routine that will be called when the
|
|
* timer expires (and interrupt occurs). The \a chbsp_periodic_timer_handler function
|
|
* will call this function.
|
|
*/
|
|
// uint8_t chbsp_periodic_timer_init(uint16_t interval_ms, ch_timer_callback_t callback_func_ptr) {
|
|
// static bool is_hw_init_done = false;
|
|
|
|
// /* Save timer interval and callback function */
|
|
// periodic_timer_interval_ms = interval_ms;
|
|
// periodic_timer_callback_ptr = callback_func_ptr;
|
|
|
|
// /* Initialize the HW only 1 time at startup. Skip the init on subsequent calls. */
|
|
// if (!is_hw_init_done) {
|
|
// /* Configure the PMC to enable the TC module and channels */
|
|
// sysclk_enable_peripheral_clock(ID_TC0);
|
|
// sysclk_enable_peripheral_clock(ID_TC1);
|
|
// /* Create on PCK3 a 499985 Hz clock from the PLLA clock. */
|
|
// pmc_disable_pck(PMC_PCK_3);
|
|
// pmc_switch_pck_to_pllack(PMC_PCK_3, PMC_PCK_PRES(240 - 1));
|
|
// pmc_enable_pck(PMC_PCK_3);
|
|
|
|
// /* Reset all TC0 counters */
|
|
// TC0->TC_BCR = TC_BCR_SYNC;
|
|
|
|
// /* Enable TC0 - Channel 0 interrupt */
|
|
// NVIC_DisableIRQ(TC0_IRQn);
|
|
// NVIC_ClearPendingIRQ(TC0_IRQn);
|
|
// NVIC_SetPriority(TC0_IRQn, 1);
|
|
// NVIC_EnableIRQ(TC0_IRQn);
|
|
|
|
// /* Enable TC0 - Channel 1 interrupt */
|
|
// NVIC_DisableIRQ(TC1_IRQn);
|
|
// NVIC_ClearPendingIRQ(TC1_IRQn);
|
|
// NVIC_SetPriority(TC1_IRQn, 1);
|
|
// NVIC_EnableIRQ(TC1_IRQn);
|
|
|
|
// /* Create the lsepoch timer running on PCK3 and start it immediately */
|
|
// tc_init(TC0, TC_CHANNEL_LSEPOCH,
|
|
// TC_CMR_TCCLKS_TIMER_CLOCK5 | TC_CMR_WAVE | TC_CMR_WAVSEL_UP);
|
|
// tc_enable_interrupt(TC0, TC_CHANNEL_LSEPOCH, TC_IER_COVFS);
|
|
// tc_start(TC0, TC_CHANNEL_LSEPOCH);
|
|
|
|
// /* Create the ultrasound periodic timer. */
|
|
// tc_init(TC0, TC_CHANNEL_US,
|
|
// TC_CMR_TCCLKS_TIMER_CLOCK5 | TC_CMR_WAVE | TC_CMR_WAVSEL_UP);
|
|
// }
|
|
|
|
// /* Mark the HW init as done */
|
|
// is_hw_init_done = true;
|
|
|
|
// /* Convert the ODR in ms to ticks */
|
|
// ultrasound_timer_period_in_tick = get_period_in_tick(interval_ms * 1000);
|
|
|
|
// return 0;
|
|
// }
|
|
|
|
// void chbsp_periodic_timer_change_period(uint32_t new_interval_us)
|
|
// {
|
|
// uint16_t prev_expiration = ultrasound_prev_period_end_in_tick - ultrasound_timer_period_in_tick;
|
|
|
|
// ultrasound_timer_period_in_tick = get_period_in_tick(new_interval_us);
|
|
|
|
// ultrasound_prev_period_end_in_tick = prev_expiration;
|
|
|
|
// program_next_period();
|
|
// }
|
|
|
|
// uint32_t get_period_in_tick(uint32_t interval_us) {
|
|
// uint64_t timer_period_in_tick = (uint64_t) ULTRASOUND_TIMER_FREQUENCY * interval_us / 1000000;
|
|
|
|
// /* If the ODR is too slow to be handled then program a faster interrupt and decimate it */
|
|
// if (timer_period_in_tick > UINT16_MAX)
|
|
// decimation_factor = timer_period_in_tick / UINT16_MAX + 1;
|
|
// else
|
|
// decimation_factor = 1;
|
|
|
|
// /* Calculate the final tick in case a decimation is needed */
|
|
// return (uint32_t) (timer_period_in_tick / decimation_factor);
|
|
// }
|
|
|
|
// void program_next_period(void)
|
|
// {
|
|
// uint32_t time = ultrasound_prev_period_end_in_tick + ultrasound_timer_period_in_tick;
|
|
// ultrasound_prev_period_end_in_tick = time;
|
|
// tc_write_rc(TC0, TC_CHANNEL_US, (uint16_t) (time & 0xFFFF));
|
|
// }
|
|
|
|
/*!
|
|
* \brief Enable periodic timer interrupt.
|
|
*
|
|
* This function enables the interrupt associated with the periodic timer initialized by
|
|
* \a chbsp_periodic_timer_init().
|
|
*/
|
|
// void chbsp_periodic_timer_irq_enable(void) {
|
|
|
|
// /* Clear any pending CPCS before enabling it */
|
|
// tc_get_status(TC0, TC_CHANNEL_US);
|
|
// tc_enable_interrupt(TC0, TC_CHANNEL_US, TC_IER_CPCS);
|
|
// }
|
|
|
|
/*!
|
|
* \brief Disable periodic timer interrupt.
|
|
*
|
|
* This function enables the interrupt associated with the periodic timer initialized by
|
|
* \a chbsp_periodic_timer_init().
|
|
*/
|
|
// void chbsp_periodic_timer_irq_disable(void) {
|
|
|
|
// tc_disable_interrupt(TC0, TC_CHANNEL_US, TC_IDR_CPCS);
|
|
// }
|
|
|
|
/*!
|
|
* \brief Start periodic timer.
|
|
*
|
|
* \return 0 if successful, 1 if error
|
|
*
|
|
* This function starts the periodic timer initialized by \a chbsp_periodic_timer_init().
|
|
*/
|
|
// uint8_t chbsp_periodic_timer_start(void) {
|
|
|
|
// decimation_counter = 0;
|
|
// /* The timer start done at the very end is resetting the counter */
|
|
// ultrasound_prev_period_end_in_tick = 0;
|
|
// program_next_period();
|
|
|
|
// /* Start the HW counter (this resets the counter */
|
|
// tc_start(TC0, TC_CHANNEL_US);
|
|
|
|
// return 0;
|
|
// }
|
|
|
|
/*!
|
|
* \brief Turn on an LED on the board.
|
|
*
|
|
* This function turns on an LED on the board.
|
|
*
|
|
* The \a dev_num parameter contains the device number of a specific sensor. This routine
|
|
* will turn on the LED on the Chirp sensor daughterboard that is next to the specified
|
|
* sensor.
|
|
*/
|
|
void chbsp_led_on(uint8_t led_num) {
|
|
|
|
sensor_led_on();
|
|
}
|
|
|
|
/*!
|
|
* \brief Turn off an LED on the board.
|
|
*
|
|
* This function turns off an LED on the board.
|
|
*
|
|
* The \a dev_num parameter contains the device number of a specific sensor. This routine
|
|
* will turn off the LED on the Chirp sensor daughterboard that is next to the specified
|
|
* sensor.
|
|
*/
|
|
void chbsp_led_off(uint8_t led_num) {
|
|
|
|
sensor_led_off();
|
|
}
|
|
|
|
/*!
|
|
* \brief Toggles an LED on the board.
|
|
*
|
|
* This function toggles an LED on the board.
|
|
*
|
|
* The \a dev_num parameter contains the device number of a specific sensor. This routine
|
|
* will toggles the LED on the Chirp sensor daughterboard that is next to the specified
|
|
* sensor.
|
|
*/
|
|
void chbsp_led_toggle(uint8_t led_num) {
|
|
|
|
sensor_led_toggle();
|
|
}
|
|
|
|
/*!
|
|
* \brief Output a text string via serial interface
|
|
*
|
|
* \param str pointer to a string of characters to be output
|
|
*
|
|
* This function prints debug information to the console.
|
|
*/
|
|
void chbsp_print_str(char *str) {
|
|
printf("%s", str);
|
|
}
|
|
|
|
/*!
|
|
* \brief Return the current time in ms
|
|
*
|
|
* This function returns the system current time in ms.
|
|
*/
|
|
// uint32_t chbsp_timestamp_ms(void) {
|
|
// uint32_t time = time_get_in_us();
|
|
// return (time / 1000);
|
|
// }
|
|
|
|
/************* End of file chbsp_chirp_smartsonic.c -- Copyright 2016-2019 Chirp Microsystems **********/ |