// for GD32VF103 #ifndef _MRBC_API_H #define _MRBC_API_H #include "gd32vf103.h" // GPIO #define MRBC_GPIO_IN GPIO_MODE_IN_FLOATING #define MRBC_GPIO_OUT GPIO_MODE_OUT_PP #define MRBC_GPIO_IN_PU GPIO_MODE_IPU #define MRBC_GPIO_IN_PD GPIO_MODE_IPD #define MRBC_GPIO_OUT_OD GPIO_MODE_OUT_OD #define MRBC_GPIO_IN_ANALOG GPIO_MODE_AIN static inline void mrbcPinMode(uint8_t pin_id, uint32_t mode) { uint8_t port_num = (pin_id >> 4) & 0x0F; uint8_t pin_num = pin_id & 0x0F; if (port_num > 4) return; uint32_t gpio_periph = GPIO_BASE + ((uint32_t)port_num << 10); rcu_periph_enum rcu_clk = (rcu_periph_enum)(RCU_GPIOA + port_num); uint32_t pin_mask = (1U << pin_num); rcu_periph_clock_enable(rcu_clk); gpio_init(gpio_periph, mode, GPIO_OSPEED_50MHZ, pin_mask); } static inline void mrbcDigitalWrite(uint8_t pin_id, uint8_t value) { uint8_t port_num = (pin_id >> 4) & 0x0F; uint8_t pin_num = pin_id & 0x0F; uint32_t gpio_periph = GPIO_BASE + ((uint32_t)port_num << 10); uint32_t pin_mask = (1U << pin_num); if (value) { gpio_bit_set(gpio_periph, pin_mask); } else { gpio_bit_reset(gpio_periph, pin_mask); } } static inline uint8_t mrbcDigitalRead(uint8_t pin_id) { uint8_t port_num = (pin_id >> 4) & 0x0F; uint8_t pin_num = pin_id & 0x0F; uint32_t gpio_periph = GPIO_BASE + ((uint32_t)port_num << 10); uint32_t pin_mask = (1U << pin_num); return (gpio_input_bit_get(gpio_periph, pin_mask) == SET) ? 1 : 0; } // ADC #define MRBC_ADC_RANGE 4095 //1023 #define MRBC_ADC_REF 3.3 //5.0 #define MRBC_ADC_TIMEOUT_MAX 100000 static inline uint8_t mrbcAnalogChannel(uint8_t pin_id) { // PA0-7 PB0-1 uint8_t port_num = (pin_id >> 4) & 0x0F; uint8_t pin_num = pin_id & 0x0F; if (port_num == 0 && pin_num <= 7) { return pin_num; } else if (port_num == 1 && pin_num <= 1) { return pin_num + 8; } return 0xFF; } static inline uint8_t mrbcAnalogInit(uint8_t pin_id) { uint8_t ch = mrbcAnalogChannel(pin_id); if (ch == 0xFF) return 0xff; mrbcPinMode(pin_id,MRBC_GPIO_IN_ANALOG); rcu_periph_clock_enable(RCU_ADC0); rcu_adc_clock_config(RCU_CKADC_CKAPB2_DIV6); adc_deinit(ADC0); adc_mode_config(ADC_MODE_FREE); adc_special_function_config(ADC0, ADC_SCAN_MODE, DISABLE); adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, DISABLE); adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT); adc_external_trigger_source_config(ADC0, ADC_REGULAR_CHANNEL, ADC0_1_EXTTRIG_REGULAR_NONE); adc_external_trigger_config(ADC0, ADC_REGULAR_CHANNEL, ENABLE); adc_channel_length_config(ADC0, ADC_REGULAR_CHANNEL, 1); adc_enable(ADC0); adc_calibration_enable(ADC0); return ch; } static inline uint16_t mrbcAnalogRead(uint8_t ch) { adc_regular_channel_config(ADC0, 0, ch, ADC_SAMPLETIME_55POINT5); adc_software_trigger_enable(ADC0, ADC_REGULAR_CHANNEL); uint32_t timeout = MRBC_ADC_TIMEOUT_MAX; while (adc_flag_get(ADC0, ADC_FLAG_EOC) == RESET){ if (--timeout == 0) return 0; } adc_flag_clear(ADC0, ADC_FLAG_EOC); return adc_regular_data_read(ADC0); } // PWM static volatile uint8_t pin_timer[]={ // timer, map, ch 0100,0101,0102,0103,0,0,0,0, 0,0,0,0,0,0,0,0, 0222,0223,0,0,0220,0221,0300,0301, 0302,0303, }; static const uint32_t timer_base_table[] = { 0, TIMER1, TIMER2, TIMER3 }; static const rcu_periph_enum timer_rcu_table[] = { 0, RCU_TIMER1, RCU_TIMER2, RCU_TIMER3 }; static const rcu_periph_enum timer_remap_table[] = { 0, GPIO_TIMER1_FULL_REMAP, GPIO_TIMER2_FULL_REMAP, 0 }; static inline void mrbcPwmWrite(uint8_t pin, uint32_t freq, uint16_t duty) { if(freq==0){ mrbcDigitalWrite(pin,0); mrbcPinMode(pin, MRBC_GPIO_OUT); return; } uint32_t limit=SystemCoreClock/freq; uint32_t prescaler=limit>>16; limit/=(prescaler+1); uint16_t val=limit*duty/10000; if(limit>0) limit--; if(pin>=sizeof(pin_timer)) return; uint8_t tmr=pin_timer[pin]; if(tmr == 0) return; uint8_t ch=tmr%8; uint8_t alt=(tmr/8)%8; // remap tmr>>=6; rcu_periph_clock_enable(RCU_AF); uint32_t timer_periph = timer_base_table[tmr]; rcu_periph_enum timer_rcu = timer_rcu_table[tmr]; rcu_periph_clock_enable(timer_rcu); if (alt == 2) { gpio_pin_remap_config(GPIO_SWJ_NONJTRST_REMAP, ENABLE); gpio_pin_remap_config(timer_remap_table[tmr], ENABLE); } //timer_deinit(timer_periph); timer_oc_parameter_struct my_ocinitpara = {0}; my_ocinitpara.outputstate = TIMER_CCX_ENABLE; timer_channel_output_mode_config(timer_periph, ch, TIMER_OC_MODE_PWM0); timer_channel_output_config(timer_periph, ch, &my_ocinitpara); TIMER_PSC(timer_periph)=prescaler; TIMER_CAR(timer_periph)=limit; volatile uint32_t *ch_val_reg = &(TIMER_CH0CV(timer_periph)); ch_val_reg[ch] = val; TIMER_SWEVG(timer_periph) |= (uint32_t)TIMER_SWEVG_UPG; timer_auto_reload_shadow_enable(timer_periph); timer_enable(timer_periph); mrbcPinMode(pin, GPIO_MODE_AF_PP); } // I2C #define NO_I2C_HANDLE #define I2C_TIMEOUT_MAX 100000 #define I2C_WAIT_FLAG(periph, flag) do { \ uint32_t timeout = I2C_TIMEOUT_MAX; \ while (RESET == i2c_flag_get((periph), (flag))) { \ if (--timeout == 0) return -1; \ } \ } while(0) #define MY_I2C I2C0 static inline void mrbcI2cInit(void* handle, uint32_t freq, int scl, int sda) { rcu_periph_clock_enable(RCU_GPIOB); rcu_periph_clock_enable(RCU_I2C0); // PB6(SCL), PB7(SDA) gpio_init(GPIOB, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_6 | GPIO_PIN_7); i2c_deinit(MY_I2C); i2c_clock_config(MY_I2C, freq, I2C_DTCY_2); // duty 2 i2c_mode_addr_config(MY_I2C, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0x70); i2c_ack_config(MY_I2C, I2C_ACK_ENABLE); i2c_enable(MY_I2C); } static inline int mrbcI2cStart(void* handle, uint8_t adrs, uint8_t rw) // rw=1 if read { uint32_t wait_bus = I2C_TIMEOUT_MAX; while(i2c_flag_get(MY_I2C, I2C_FLAG_I2CBSY)) { if (--wait_bus == 0) return -1; } i2c_start_on_bus(MY_I2C); I2C_WAIT_FLAG(MY_I2C, I2C_FLAG_SBSEND); uint8_t direction = (rw == 1) ? I2C_RECEIVER : I2C_TRANSMITTER; i2c_master_addressing(MY_I2C, adrs, direction); I2C_WAIT_FLAG(MY_I2C, I2C_FLAG_ADDSEND); i2c_flag_clear(MY_I2C, I2C_FLAG_ADDSEND); return 0; } static inline void mrbcI2cStop(void* handle) { i2c_stop_on_bus(MY_I2C); } static inline int mrbcI2cWrite(void* handle, const uint8_t *buf, uint16_t len) { for (uint16_t i = 0; i < len; i++) { I2C_WAIT_FLAG(MY_I2C, I2C_FLAG_TBE); i2c_data_transmit(MY_I2C, buf[i]); } I2C_WAIT_FLAG(MY_I2C, I2C_FLAG_BTC); return 0; } static inline int mrbcI2cRead(void* handle, uint8_t *buf, uint16_t len) { if (len == 0) return 0; i2c_ack_config(MY_I2C, I2C_ACK_ENABLE); for (uint16_t i = 0; i < len; i++) { if (i == (len - 1)) { i2c_ack_config(MY_I2C, I2C_ACK_DISABLE); i2c_stop_on_bus(MY_I2C); } I2C_WAIT_FLAG(MY_I2C, I2C_FLAG_RBNE); buf[i] = i2c_data_receive(MY_I2C); } i2c_ack_config(MY_I2C, I2C_ACK_ENABLE); return 0; } // SPI #define MRBC_SPI_LSB_FIRST SPI_ENDIAN_LSB #define MRBC_SPI_MSB_FIRST SPI_ENDIAN_MSB #define NO_SPI_HANDLE #define MY_SPI SPI1 #define SPI_TIMEOUT_MAX 100000 #define SPI_WAIT_FLAG(periph, flag) do { \ uint32_t timeout = SPI_TIMEOUT_MAX; \ while (RESET == spi_i2s_flag_get((periph), (flag))) { \ if (--timeout == 0) return; \ } \ } while(0) static inline void mrbcSpiInit(void* handle) { rcu_periph_clock_enable(RCU_GPIOB); rcu_periph_clock_enable(RCU_SPI1); // PB13(SCK), PB15(MOSI) gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_13 | GPIO_PIN_15); // PB14(MISO) gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_14); } static inline void mrbcSpiMode(void* handle, uint32_t spi_freq, uint32_t spi_first_bit, uint32_t spi_mode) { const uint32_t spi_bus_clk = 54000000; uint32_t ratio = spi_bus_clk / spi_freq; uint8_t scale = 0; if (ratio > 0) ratio--; while (ratio >>= 1) scale++; if (scale > 7) scale = 7; spi_parameter_struct spi_init_struct; spi_init_struct.trans_mode = SPI_TRANSMODE_FULLDUPLEX; spi_init_struct.device_mode = SPI_MASTER; spi_init_struct.frame_size = SPI_FRAMESIZE_8BIT; spi_init_struct.nss = SPI_NSS_SOFT; spi_init_struct.prescale = ((uint32_t)scale << 3); //SPI_PSC_8; spi_init_struct.endian = spi_first_bit; spi_init_struct.clock_polarity_phase = (uint32_t)spi_mode; //SPI_CK_PL_LOW_PH_1EDGE; spi_init(MY_SPI, &spi_init_struct); spi_enable(MY_SPI); } static inline void mrbcSpiTransfer(void* handle, uint8_t *buf, uint32_t len) { for (uint32_t i = 0; i < len; i++) { SPI_WAIT_FLAG(MY_SPI, SPI_FLAG_TBE); spi_i2s_data_transmit(MY_SPI, buf[i]); SPI_WAIT_FLAG(MY_SPI, SPI_FLAG_RBNE); buf[i] = spi_i2s_data_receive(MY_SPI); } SPI_WAIT_FLAG(MY_SPI, SPI_FLAG_TRANS); } // UART #define MRBC_UART_NONE USART_PM_NONE #define MRBC_UART_EVEN USART_PM_EVEN #define MRBC_UART_ODD USART_PM_ODD #define UART_BUF_SIZE 128 typedef struct UART_HANDLE { uint8_t unit_num; uint8_t rx_index; char rx_buf[UART_BUF_SIZE]; } UART_HANDLE; static const uint32_t usart_base_table[] = { USART0, USART1 }; static const rcu_periph_enum usart_rcu_table[] = { RCU_USART0, RCU_USART1 }; static const uint8_t rx_pin_num[]={10,3}; static const uint8_t tx_pin_num[]={9,2}; static const uint32_t usart_dma_ch_table[] = { DMA_CH4, DMA_CH5 }; #define UART_TIMEOUT_MAX 100000 static inline void mrbcUartInit(UART_HANDLE *handle) { int unit_num = handle->unit_num; handle->rx_index = 0; uint32_t usart_periph = usart_base_table[unit_num]; rcu_periph_enum usart_rcu = usart_rcu_table[unit_num]; uint32_t dma_ch = usart_dma_ch_table[unit_num]; uint8_t tx = tx_pin_num[unit_num]; uint8_t rx = rx_pin_num[unit_num]; rcu_periph_clock_enable(usart_rcu); rcu_periph_clock_enable(RCU_DMA0); mrbcPinMode(tx,GPIO_MODE_AF_PP); mrbcPinMode(rx,GPIO_MODE_IN_FLOATING); usart_deinit(usart_periph); usart_hardware_flow_rts_config(usart_periph, USART_RTS_DISABLE); usart_hardware_flow_cts_config(usart_periph, USART_CTS_DISABLE); usart_receive_config(usart_periph, USART_RECEIVE_ENABLE); usart_transmit_config(usart_periph, USART_TRANSMIT_ENABLE); dma_parameter_struct dma_init_struct; dma_deinit(DMA0, dma_ch); dma_circulation_enable(DMA0, dma_ch); dma_init_struct.periph_addr = (uint32_t)&USART_DATA(usart_periph); dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; dma_init_struct.memory_addr = (uint32_t)handle->rx_buf; dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY; dma_init_struct.number = UART_BUF_SIZE; dma_init_struct.priority = DMA_PRIORITY_HIGH; dma_init(DMA0, dma_ch, &dma_init_struct); dma_channel_enable(DMA0, dma_ch); usart_dma_receive_config(usart_periph, USART_DENR_ENABLE); } static inline void mrbcUartSetMode(UART_HANDLE *handle, uint32_t baud_rate, uint32_t datb, uint32_t stpb, uint32_t prty ) { uint32_t usart_periph = usart_base_table[handle->unit_num]; usart_baudrate_set(usart_periph, baud_rate); /* usart->CTLR2 = (stpb&2)<<12; // 1:1bit, 2:2bit, //3:0.5, 4:1.5 0213 usart->CTLR1 = USART_WordLength_9b * (prty>0 && datb>7) | (prty&3)<<9 | USART_Mode_Tx | USART_Mode_Rx | CTLR1_UE_Set; */ if(datb>7 && prty!=USART_PM_NONE){ usart_word_length_set(usart_periph, USART_WL_9BIT); }else{ usart_word_length_set(usart_periph, USART_WL_8BIT); } switch (stpb) { case 4: usart_stop_bit_set(usart_periph, USART_STB_1_5BIT); break; case 3: usart_stop_bit_set(usart_periph, USART_STB_0_5BIT); break; case 2: usart_stop_bit_set(usart_periph, USART_STB_2BIT); break; default: usart_stop_bit_set(usart_periph, USART_STB_1BIT); break; } usart_parity_config(usart_periph, prty); usart_enable(usart_periph); } static inline int mrbcUartByteToWrite(UART_HANDLE *handle) { return 0; } static inline int mrbcUartWrite(UART_HANDLE *handle, const char *buf, int size){ uint32_t usart_periph = usart_base_table[handle->unit_num]; for(int i = 0; i < size; i++){ uint32_t timeout = UART_TIMEOUT_MAX; while (0 == (USART_STAT(usart_periph) & USART_STAT_TBE)) { if (--timeout == 0) return -1;} USART_DATA(usart_periph) = (uint16_t)*buf++; } return size; } static inline int mrbcUartAvailable(UART_HANDLE *handle){ uint32_t dma_ch = usart_dma_ch_table[handle->unit_num]; uint8_t size =(UART_BUF_SIZE - dma_transfer_number_get(DMA0, dma_ch)); //%UART_BUF_SIZE; size -= handle->rx_index; size %= UART_BUF_SIZE; return size; } static inline int mrbcUartRead(UART_HANDLE *handle, char *buf, int size){ for(int i = 0; i < size; i++){ while(!mrbcUartAvailable(handle)); buf[i] = handle->rx_buf[handle->rx_index]; handle->rx_index = (handle->rx_index + 1)%UART_BUF_SIZE; } buf[size] = '\0'; return size; } static inline int mrbcUartCanReadLine(UART_HANDLE *handle){ uint32_t dma_ch = usart_dma_ch_table[handle->unit_num]; uint8_t index = handle->rx_index; uint8_t last = (UART_BUF_SIZE - dma_transfer_number_get(DMA0, dma_ch))%UART_BUF_SIZE; while( index != last ) { if( handle->rx_buf[index++] == '\n' )return (index - handle->rx_index)%UART_BUF_SIZE; index%=UART_BUF_SIZE; } return 0; } static inline void mrbcUartFlush(UART_HANDLE *handle) { } static inline void mrbcUartClearRx(UART_HANDLE *handle) { uint32_t dma_ch = usart_dma_ch_table[handle->unit_num]; handle->rx_index=(UART_BUF_SIZE - dma_transfer_number_get(DMA0, dma_ch))%UART_BUF_SIZE; } static inline void mrbcUartClearTx(UART_HANDLE *handle) { } // DAC #endif