add doxygen documentation
This commit is contained in:
parent
d6f3efb001
commit
3a0d9e6186
1
.gitignore
vendored
1
.gitignore
vendored
@ -7,3 +7,4 @@
|
||||
*.elf
|
||||
*.bin
|
||||
*.swp
|
||||
doc
|
||||
|
6
Makefile
6
Makefile
@ -30,6 +30,7 @@ BOARD = SYSTEM_BOARD
|
||||
|
||||
# source files
|
||||
CSRC = $(wildcard *.c)
|
||||
CHDR = $(wildcard *.h)
|
||||
OBJ = $(patsubst %.c,%.o,$(CSRC))
|
||||
# figure out based on the includes which library files are used in the main CSRC files
|
||||
DEPENDENCIES = $(patsubst %.c,%.inc,$(CSRC))
|
||||
@ -39,6 +40,7 @@ LIB = lib
|
||||
# the library files to use
|
||||
# this will be populated using includes based DEPENDENCIES
|
||||
LIB_CSRC =
|
||||
LIB_CHDR = $(patsubst %.c,%.h,$(LIB_CSRC))
|
||||
LIB_OBJ = $(patsubst %.c,%.o,$(LIB_CSRC))
|
||||
# populates LIB_CSRC based on the library files used
|
||||
-include $(DEPENDENCIES)
|
||||
@ -164,6 +166,10 @@ list: $(BINARY).list
|
||||
%.inc: %.d
|
||||
$(Q)grep -o -e " ${LIB}\/[^ ]*\.h" $(<) | sed -e 's/\.h$$/.c/g' -e 's/^/LIB_CSRC +=/' > $(@)
|
||||
|
||||
# doxygen documentation
|
||||
doc: Doxyfile $(CSRC) $(CHDR) $(LIB_CSRC) $(LIB_CHDR)
|
||||
$(Q)doxygen $(<)
|
||||
|
||||
clean:
|
||||
$(Q)$(RM) $(BINARY).elf $(BINARY).bin $(BINARY).hex $(BINARY).map $(OBJ) $(LIB_OBJ) $(LIB)/*.o $(DEPENDENCIES)
|
||||
|
||||
|
@ -104,4 +104,7 @@ this allows to restart the bootloader and flash new firmware using DFU.
|
||||
to reset the board run `make reset`.
|
||||
this only works if the USB CDC ACM run correctly and the micro-controller isn't stuck.
|
||||
|
||||
documentation
|
||||
=============
|
||||
|
||||
to generate doxygen documentation run `make doc`.
|
||||
|
36
global.h
36
global.h
@ -12,36 +12,40 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
/* Copyright (c) 2016 King Kévin <kingkevin@cuvoodoo.info> */
|
||||
/** @brief global definitions and methods
|
||||
* @file global.h
|
||||
* @author King Kévin <kingkevin@cuvoodoo.info>
|
||||
* @date 2016
|
||||
*/
|
||||
#pragma once
|
||||
#include <libopencm3/stm32/gpio.h> // GPIO defines
|
||||
#include <libopencm3/cm3/nvic.h> // interrupt defines
|
||||
#include <libopencm3/stm32/exti.h> // external interrupt defines
|
||||
|
||||
/* get the length of an array */
|
||||
/** get the length of an array */
|
||||
#define LENGTH(x) (sizeof(x) / sizeof((x)[0]))
|
||||
|
||||
/* LED pin */
|
||||
/* board LED GPIO */
|
||||
#if defined(SYSTEM_BOARD)
|
||||
/* on system board LED is on pin 11/PA1 */
|
||||
#define LED_RCC RCC_GPIOA
|
||||
/** on system board LED is on pin 11/PA1 */
|
||||
#define LED_RCC RCC_GPIOA
|
||||
#define LED_PORT GPIOA
|
||||
#define LED_PIN GPIO1
|
||||
#elif defined(BLUE_PILL)
|
||||
/* on minimum system LED is on pin 2/PC13 */
|
||||
/** on minimum system LED is on pin 2/PC13 */
|
||||
#define LED_RCC RCC_GPIOC
|
||||
#define LED_PORT GPIOC
|
||||
#define LED_PIN GPIO13
|
||||
#elif defined (MAPLE_MINI)
|
||||
/* on maple mini LED is on pin 19/PB1 */
|
||||
/** on maple mini LED is on pin 19/PB1 */
|
||||
#define LED_RCC RCC_GPIOB
|
||||
#define LED_PORT GPIOB
|
||||
#define LED_PIN GPIO1
|
||||
#endif
|
||||
|
||||
/* user button */
|
||||
/* board user button GPIO */
|
||||
#if defined(MAPLE_MINI)
|
||||
/* on maple mini button is on 32/PB8 */
|
||||
/** on maple mini user button is on 32/PB8 */
|
||||
#define BUTTON_RCC RCC_GPIOB
|
||||
#define BUTTON_PORT GPIOB
|
||||
#define BUTTON_PIN GPIO8
|
||||
@ -50,14 +54,18 @@
|
||||
#define BUTTON_ISR exti9_5_isr
|
||||
#endif
|
||||
|
||||
/* switch on LED */
|
||||
/** @brief switch on board LED */
|
||||
void led_on(void);
|
||||
/* switch off LED */
|
||||
/** @brief switch off board LED */
|
||||
void led_off(void);
|
||||
/* toggle LED */
|
||||
/** @brief toggle board LED */
|
||||
void led_toggle(void);
|
||||
/* default output (i.e. for printf) */
|
||||
/** @brief default printf output */
|
||||
int _write(int file, char *ptr, int len);
|
||||
/* print binary as string */
|
||||
/** @brief get binary representation of a number
|
||||
* @param[in] binary number to represent in binary
|
||||
* @param[in] rjust justify representation with leading zeros
|
||||
* @return string with binary representation of the number
|
||||
*/
|
||||
char* b2s(uint32_t binary, uint8_t rjust);
|
||||
|
||||
|
@ -12,9 +12,12 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
/* Copyright (c) 2016 King Kévin <kingkevin@cuvoodoo.info> */
|
||||
/* this library is used to drive a WS2812b LED chain */
|
||||
/* peripherals used: SPI , timer, DMA (check source for details) */
|
||||
/** @brief library to drive a WS2812b LED chain (code)
|
||||
* @file led_ws2812b.c
|
||||
* @author King Kévin <kingkevin@cuvoodoo.info>
|
||||
* @date 2016
|
||||
* @note peripherals used: SPI @ref led_ws2812b_spi, timer @ref led_ws2812b_timer, DMA @ref led_ws2812b_dma
|
||||
*/
|
||||
|
||||
/* standard libraries */
|
||||
#include <stdint.h> // standard integer types
|
||||
@ -32,38 +35,50 @@
|
||||
#include "led_ws2812b.h" // LED WS2812b library API
|
||||
#include "global.h" // global definitions
|
||||
|
||||
/* WS2812b peripheral configuration */
|
||||
#define WS2812B_SPI SPI1
|
||||
#define WS2812B_SPI_DR SPI1_DR
|
||||
#define WS2812B_SPI_RCC RCC_SPI1
|
||||
#define WS2812B_SPI_PORT GPIOA
|
||||
#define WS2812B_SPI_CLK GPIO_SPI1_SCK // connect PWM output to clock input on PA5
|
||||
#define WS2812B_SPI_DOUT GPIO_SPI1_MISO // connect WS2812b DIN to MISO pin PA6
|
||||
#define WS2812B_TIMER TIM3
|
||||
#define WS2812B_TIMER_RCC RCC_TIM3
|
||||
#define WS2812B_TIMER_OC TIM_OC3
|
||||
#define WS2812B_CLK_RCC RCC_GPIOB
|
||||
#define WS2812B_CLK_PORT GPIOB
|
||||
#define WS2812B_CLK_PIN GPIO_TIM3_CH3 // connect SPI clock input to PWM clock output PB0
|
||||
#define WS2812B_DMA DMA1 // DMA1 supports SPI1_TX interrupt
|
||||
#define WS2812B_DMA_RCC RCC_DMA1 // follows previous definition
|
||||
#define WS2812B_DMA_CH DMA_CHANNEL3 // only DMA1 channel 3 supports SPI1_TX interrupt
|
||||
#define WS2812B_DMA_IRQ NVIC_DMA1_CHANNEL3_IRQ // follows previous definition
|
||||
#define WS2812B_DMA_ISR dma1_channel3_isr // follows previous definition
|
||||
/** peripheral configuration */
|
||||
/** @defgroup led_ws2812b_spi SPI peripheral used to control the WS2812b LEDs
|
||||
* @{
|
||||
*/
|
||||
#define WS2812B_SPI SPI1 /**< SPI peripheral */
|
||||
#define WS2812B_SPI_DR SPI1_DR /**< SPI data register for the DMA */
|
||||
#define WS2812B_SPI_RCC RCC_SPI1 /**< SPI peripheral clock */
|
||||
#define WS2812B_SPI_PORT GPIOA /**< SPI port */
|
||||
#define WS2812B_SPI_CLK GPIO_SPI1_SCK /**< SPI clock pin (PA5), connect to PWM output */
|
||||
#define WS2812B_SPI_DOUT GPIO_SPI1_MISO /**< SPI data pin (PA6), connect to WS2812b DIN */
|
||||
/** @} */
|
||||
/** @defgroup led_ws2812b_timer timer peripheral used to generate SPI clock
|
||||
* @{
|
||||
*/
|
||||
#define WS2812B_TIMER TIM3 /**< timer peripheral */
|
||||
#define WS2812B_TIMER_RCC RCC_TIM3 /**< timer peripheral clock */
|
||||
#define WS2812B_TIMER_OC TIM_OC3 /**< timer output compare used to set PWM frequency */
|
||||
#define WS2812B_CLK_RCC RCC_GPIOB /**< timer port peripheral clock */
|
||||
#define WS2812B_CLK_PORT GPIOB /**< timer port */
|
||||
#define WS2812B_CLK_PIN GPIO_TIM3_CH3 /**< timer pin to output PWM (PB0), connect to SPI clock input */
|
||||
/** @} */
|
||||
/** @defgroup led_ws2812b_dma DMA peripheral used to send the data
|
||||
* @{
|
||||
*/
|
||||
#define WS2812B_DMA DMA1 /**< DMA peripheral to put data for WS2812b LED in SPI queue (only DMA1 supports SPI1_TX interrupt) */
|
||||
#define WS2812B_DMA_RCC RCC_DMA1 /**< DMA peripheral clock */
|
||||
#define WS2812B_DMA_CH DMA_CHANNEL3 /**< DMA channel (only DMA1 channel 3 supports SPI1_TX interrupt) */
|
||||
#define WS2812B_DMA_IRQ NVIC_DMA1_CHANNEL3_IRQ /**< DMA channel interrupt signal */
|
||||
#define WS2812B_DMA_ISR dma1_channel3_isr /**< DMA channel interrupt service routine */
|
||||
/** @} */
|
||||
|
||||
/* template to encode one byte
|
||||
* for each WS2812b bit which needs to be transfered we require to transfer 3 SPI bits
|
||||
* the first SPI bit is the high start of the WS2812b bit frame
|
||||
* the second SPI bit determines if the WS2812b bit is a 0 or 1
|
||||
* the third SPI bit is the last part of the WS2812b bit frame, which is always low
|
||||
* only the first 24 bits (3*8) are used */
|
||||
#define WS2812B_SPI_TEMPLATE 0x92492400 //0b10010010010010010010010000000000
|
||||
/** @brief bit template to encode one byte to be shifted out by SPI to the WS2812b LEDs
|
||||
* @details For each WS2812b bit which needs to be transfered we require to transfer 3 SPI bits.
|
||||
* The first SPI bit is the high start of the WS2812b bit frame.
|
||||
* The second SPI bit determines if the WS2812b bit is a 0 or 1.
|
||||
* The third SPI bit is the last part of the WS2812b bit frame, which is always low.
|
||||
* Only the first 24 bits (3*8) are used.
|
||||
* The binary pattern is 0b10010010010010010010010000000000
|
||||
*/
|
||||
#define WS2812B_SPI_TEMPLATE 0x92492400
|
||||
|
||||
uint8_t ws2812b_data[WS2812B_LEDS*3*3+40*3/8] = {0}; // SPI encode data to be shifted out for WS2812b + the 50us reset
|
||||
uint8_t ws2812b_data[WS2812B_LEDS*3*3+40*3/8] = {0}; /**< data encoded to be shifted out by SPI for the WS2812b, pulse the 50us reset */
|
||||
static volatile bool transmit_flag = false; // is transmission ongoing
|
||||
|
||||
/* set color of a single LED
|
||||
* transmission needs to be done separately */
|
||||
void ws2812b_set_rgb(uint16_t led, uint8_t red, uint8_t green, uint8_t blue)
|
||||
{
|
||||
// verify the led exists
|
||||
@ -90,7 +105,6 @@ void ws2812b_set_rgb(uint16_t led, uint8_t red, uint8_t green, uint8_t blue)
|
||||
}
|
||||
}
|
||||
|
||||
/* transmit colors to LEDs */
|
||||
void ws2812b_transmit(void)
|
||||
{
|
||||
while (transmit_flag) { // wait for previous transmission to complete
|
||||
@ -108,7 +122,6 @@ void ws2812b_transmit(void)
|
||||
timer_enable_counter(WS2812B_TIMER); // start timer to generate clock
|
||||
}
|
||||
|
||||
/* setup WS2812b LED controller */
|
||||
void ws2812b_setup(void)
|
||||
{
|
||||
/* setup timer to generate clock of (using PWM): 800kHz*3 */
|
||||
@ -160,7 +173,7 @@ void ws2812b_setup(void)
|
||||
ws2812b_transmit(); // set LEDs
|
||||
}
|
||||
|
||||
/* data transmission finished */
|
||||
/** @brief DMA interrupt service routine to stop transmission after it finished */
|
||||
void WS2812B_DMA_ISR(void)
|
||||
{
|
||||
if (dma_get_interrupt_flag(WS2812B_DMA, WS2812B_DMA_CH, DMA_TCIF)) { // transfer completed
|
||||
|
@ -12,18 +12,26 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
/* Copyright (c) 2016 King Kévin <kingkevin@cuvoodoo.info> */
|
||||
/* this library is used to drive a WS2812b LED chain */
|
||||
/* peripherals used: SPI , timer, DMA (check source for details) */
|
||||
/** @brief library to drive a WS2812b LED chain (API)
|
||||
* @file led_ws2812b.h
|
||||
* @author King Kévin <kingkevin@cuvoodoo.info>
|
||||
* @date 2016
|
||||
* @note peripherals used: SPI @ref led_ws2812b_spi, timer @ref led_ws2812b_timer, DMA @ref led_ws2812b_dma
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/* number of LEDs */
|
||||
/** number of LEDs on the WS2812b strip */
|
||||
#define WS2812B_LEDS 60
|
||||
|
||||
/* set color of a single LED
|
||||
* transmission needs to be done separately */
|
||||
void ws2812b_set_rgb(uint16_t led, uint8_t red, uint8_t green, uint8_t blue);
|
||||
/* transmit colors to LEDs */
|
||||
void ws2812b_transmit(void);
|
||||
/* setup WS2812b LED controller */
|
||||
/** @brief setup WS2812b LED driver */
|
||||
void ws2812b_setup(void);
|
||||
/** @brief set color of a single LED
|
||||
* @param[in] led the LED number to set the color
|
||||
* @param[in] red the red color value to set on the LED
|
||||
* @param[in] green the green color value to set on the LED
|
||||
* @param[in] blue the blue color value to set on the LED
|
||||
* @note transmission needs to be done separately
|
||||
*/
|
||||
void ws2812b_set_rgb(uint16_t led, uint8_t red, uint8_t green, uint8_t blue);
|
||||
/** @brief transmit color values to WS2812b LEDs */
|
||||
void ws2812b_transmit(void);
|
||||
|
@ -12,11 +12,11 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
/** @file rtc_ds1307.c
|
||||
/** @brief library to communicate with the Maxim DS1307 I2C RTC IC (code)
|
||||
* @file rtc_ds1307.c
|
||||
* @author King Kévin <kingkevin@cuvoodoo.info>
|
||||
* @date 2016
|
||||
* @brief this library handles communication with the I2C RTC IC Maxim DS1307
|
||||
* peripherals used: I2C @ref rtc_ds1307_i2c
|
||||
* @note peripherals used: I2C @ref rtc_ds1307_i2c
|
||||
*/
|
||||
|
||||
/* standard libraries */
|
||||
@ -34,26 +34,19 @@
|
||||
#include "global.h" // global utilities
|
||||
#include "rtc_ds1307.h" // RTC header and definitions
|
||||
|
||||
/** @defgroup trc_ds1307_i2c I2C port used to communication with the DS1307 RTC IC
|
||||
/** @defgroup rtc_ds1307_i2c I2C peripheral used to communication with the DS1307 RTC IC
|
||||
* @{
|
||||
*/
|
||||
/** I2C peripheral */
|
||||
#define I2C I2C1
|
||||
/** I2C peripheral clock */
|
||||
#define I2C_RCC RCC_I2C1
|
||||
/** I2C peripheral interrupt */
|
||||
#define I2C_IRQ NVIC_I2C1_EV_IRQ
|
||||
/** I2C event interrupt service routine */
|
||||
#define I2C_ISR i2c1_ev_isr
|
||||
/** I2C peripheral port */
|
||||
#define I2C_PORT GPIOB
|
||||
/** I2C peripheral data pin (PB7) */
|
||||
#define I2C_PIN_SDA GPIO_I2C1_SDA
|
||||
/** I2C peripheral clock pin (PB6) */
|
||||
#define I2C_PIN_SCL GPIO_I2C1_SCL
|
||||
#define I2C I2C1 /**< I2C peripheral */
|
||||
#define I2C_RCC RCC_I2C1 /**< I2C peripheral clock */
|
||||
#define I2C_IRQ NVIC_I2C1_EV_IRQ /**< I2C peripheral interrupt */
|
||||
#define I2C_ISR i2c1_ev_isr /**< I2C event interrupt service routine */
|
||||
#define I2C_PORT GPIOB /**< I2C peripheral port */
|
||||
#define I2C_PIN_SDA GPIO_I2C1_SDA /**< I2C peripheral data pin (PB7) */
|
||||
#define I2C_PIN_SCL GPIO_I2C1_SCL /**< I2C peripheral clock pin (PB6) */
|
||||
/** @} */
|
||||
/** DS1307 I2C address (fixed) */
|
||||
#define I2C_ADDR 0x68 //0b1101000
|
||||
#define I2C_ADDR 0x68 /**< DS1307 I2C address (fixed to 0b1101000) */
|
||||
|
||||
void rtc_setup(void)
|
||||
{
|
||||
@ -413,6 +406,7 @@ bool rtc_write_time(uint8_t seconds, uint8_t minutes, uint8_t hours, uint8_t day
|
||||
return rtc_write_memory(0, data, LENGTH(data)); // write time values on RTC
|
||||
}
|
||||
|
||||
void I2C_ISR(void) { // I2C event ISR
|
||||
/** I2C event interrupt service routine */
|
||||
void I2C_ISR(void) {
|
||||
// do nothing except wake up
|
||||
}
|
||||
|
@ -12,12 +12,12 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
/** @file rtc_ds1307.h
|
||||
/** @brief library to communicate with the Maxim DS1307 I2C RTC IC (API)
|
||||
* @file rtc_ds1307.h
|
||||
* @author King Kévin <kingkevin@cuvoodoo.info>
|
||||
* @date 2016
|
||||
* @brief this library handles communication with the I2C RTC IC Maxim DS1307
|
||||
* @todo control register and user RAM are not handled
|
||||
* peripherals used: I2C @ref rtc_ds1307_i2c
|
||||
* @note peripherals used: I2C @ref rtc_ds1307_i2c
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
@ -42,15 +42,15 @@ uint8_t rtc_read_minutes(void);
|
||||
*/
|
||||
uint8_t rtc_read_hours(void);
|
||||
/** @brief read day from RTC IC
|
||||
* @return day (1-7) of the current time, 1 being Sunday
|
||||
* @return day of the week (1-7, 1 is Sunday) of the current time, 1 being Sunday
|
||||
*/
|
||||
uint8_t rtc_read_day(void);
|
||||
/** @brief read date from RTC IC
|
||||
* @return date (day of the month, 1-31) of the current time
|
||||
* @return day of the month (1-31) of the current time
|
||||
*/
|
||||
uint8_t rtc_read_date(void);
|
||||
/** @brief read month from RTC IC
|
||||
* @return month (1-12) of the current time
|
||||
* @return month of the year (1-12) of the current time
|
||||
*/
|
||||
uint8_t rtc_read_month(void);
|
||||
/** @brief read year from RTC IC
|
||||
@ -70,48 +70,48 @@ bool rtc_oscillator_disable(void);
|
||||
*/
|
||||
bool rtc_oscillator_enable(void);
|
||||
/** @brief write seconds into RTC IC
|
||||
* @param[in] number of seconds (0-59)
|
||||
* @param[in] seconds number of seconds (0-59)
|
||||
* @return if write succeeded
|
||||
*/
|
||||
bool rtc_write_seconds(uint8_t seconds);
|
||||
/** @brief write minutes into RTC IC
|
||||
* @param[in] number of minutes (0-59)
|
||||
* @param[in] minutes number of minutes (0-59)
|
||||
* @return if write succeeded
|
||||
*/
|
||||
bool rtc_write_minutes(uint8_t minutes);
|
||||
/** @brief write hours into RTC IC
|
||||
* @param[in] number of hours (0-23)
|
||||
* @param[in] hours number of hours (0-23)
|
||||
* @return if write succeeded
|
||||
*/
|
||||
bool rtc_write_hours(uint8_t hours);
|
||||
/** @brief write day into RTC IC
|
||||
* @param[in] day (1-7, 1 is Sunday)
|
||||
* @param[in] day day of the week (1-7, 1 is Sunday)
|
||||
* @return if write succeeded
|
||||
*/
|
||||
bool rtc_write_day(uint8_t day);
|
||||
/** @brief write date into RTC IC
|
||||
* @param[in] date (day of the month, 1-31)
|
||||
* @param[in] date day of the month (1-31)
|
||||
* @return if write succeeded
|
||||
*/
|
||||
bool rtc_write_date(uint8_t date);
|
||||
/** @brief write month into RTC IC
|
||||
* @param[in] month (1-12)
|
||||
* @param[in] month month of the year (1-12)
|
||||
* @return if write succeeded
|
||||
*/
|
||||
bool rtc_write_month(uint8_t month);
|
||||
/** @brief write year into RTC IC
|
||||
* @param[in] year (2000-2099)
|
||||
* @param[in] year year (2000-2099)
|
||||
* @return if write succeeded
|
||||
*/
|
||||
bool rtc_write_year(uint16_t year);
|
||||
/** @brief write time into RTC IC
|
||||
* @param[in] number of seconds (0-59)
|
||||
* @param[in] number of minutes (0-59)
|
||||
* @param[in] number of hours (0-23)
|
||||
* @param[in] day (1-7, 1 is Sunday)
|
||||
* @param[in] date (day of the month, 1-31)
|
||||
* @param[in] month (1-12)
|
||||
* @param[in] year (2000-2099)
|
||||
* @param[in] seconds number of seconds (0-59)
|
||||
* @param[in] minutes number of minutes (0-59)
|
||||
* @param[in] hours number of hours (0-23)
|
||||
* @param[in] day day of the week (1-7, 1 is Sunday)
|
||||
* @param[in] date day of the month (1-31)
|
||||
* @param[in] month month of the year (1-12)
|
||||
* @param[in] year year (2000-2099)
|
||||
* @return if write succeeded
|
||||
*/
|
||||
bool rtc_write_time(uint8_t seconds, uint8_t minutes, uint8_t hours, uint8_t day, uint8_t date, uint8_t month, uint16_t year);
|
||||
|
49
lib/usart.c
49
lib/usart.c
@ -12,9 +12,12 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
/* Copyright (c) 2016 King Kévin <kingkevin@cuvoodoo.info> */
|
||||
/* this library handles USART communication */
|
||||
/* peripherals used: USART (check source for details) */
|
||||
/** @brief library for USART communication (code)
|
||||
* @file usart.c
|
||||
* @author King Kévin <kingkevin@cuvoodoo.info>
|
||||
* @date 2016
|
||||
* @note peripherals used: USART @ref usart
|
||||
*/
|
||||
|
||||
/* standard libraries */
|
||||
#include <stdint.h> // standard integer types
|
||||
@ -30,18 +33,19 @@
|
||||
|
||||
#include "usart.h" // USART header and definitions
|
||||
|
||||
/* which USART to use */
|
||||
#define USART USART1
|
||||
#define USART_RCC RCC_USART1
|
||||
#define USART_IRQ NVIC_USART1_IRQ
|
||||
#define USART_PORT GPIOA
|
||||
#define USART_PIN_TX GPIO_USART1_TX
|
||||
#define USART_PIN_RX GPIO_USART1_RX
|
||||
/** @defgroup usart USART peripheral used for UART communication
|
||||
* @{
|
||||
*/
|
||||
#define USART USART1 /**< USART peripheral */
|
||||
#define USART_RCC RCC_USART1 /**< USART peripheral clock */
|
||||
#define USART_IRQ NVIC_USART1_IRQ /**< USART peripheral interrupt signal */
|
||||
#define USART_ISR usart1_isr /**< USART interrupt service routine */
|
||||
#define USART_PORT GPIOA /**< USART port */
|
||||
#define USART_PIN_TX GPIO_USART1_TX /**< USART transmit pin (PA9) */
|
||||
#define USART_PIN_RX GPIO_USART1_RX /**< USART receive pin (PA10) */
|
||||
/** @} */
|
||||
|
||||
/* serial baudrate, in bits per second (with 8N1 8 bits, no parity bit, 1 stop bit settings) */
|
||||
#define USART_BAUDRATE 115200
|
||||
/* RX and TX buffer sizes */
|
||||
#define USART_BUFFER 128
|
||||
#define USART_BAUDRATE 115200 /**< serial baudrate, in bits per second (with 8N1 8 bits, no parity bit, 1 stop bit settings) */
|
||||
|
||||
/* input and output ring buffer, indexes, and available memory */
|
||||
static uint8_t rx_buffer[USART_BUFFER] = {0};
|
||||
@ -50,10 +54,8 @@ static volatile uint8_t rx_used = 0;
|
||||
static uint8_t tx_buffer[USART_BUFFER] = {0};
|
||||
static volatile uint8_t tx_i = 0;
|
||||
static volatile uint8_t tx_used = 0;
|
||||
/* show the user how much data received over USART is ready */
|
||||
volatile uint8_t usart_received = 0; // same as rx_used, but since the user can write this variable we don't rely on it
|
||||
|
||||
/* setup USART port */
|
||||
void usart_setup(void)
|
||||
{
|
||||
/* enable USART I/O peripheral */
|
||||
@ -82,14 +84,12 @@ void usart_setup(void)
|
||||
usart_received = 0;
|
||||
}
|
||||
|
||||
/* put character on USART (blocking) */
|
||||
void usart_putchar_blocking(char c)
|
||||
{
|
||||
usart_flush(); // empty buffer first
|
||||
usart_send_blocking(USART, c); // send character
|
||||
}
|
||||
|
||||
/* ensure all data has been transmitted (blocking) */
|
||||
void usart_flush(void)
|
||||
{
|
||||
while (tx_used) { // idle until buffer is empty
|
||||
@ -98,7 +98,6 @@ void usart_flush(void)
|
||||
usart_wait_send_ready(USART); // wait until transmit register is empty (transmission might not be complete)
|
||||
}
|
||||
|
||||
/* get character from USART (blocking) */
|
||||
char usart_getchar(void)
|
||||
{
|
||||
while (!rx_used) { // idle until data is available
|
||||
@ -111,7 +110,6 @@ char usart_getchar(void)
|
||||
return to_return;
|
||||
}
|
||||
|
||||
/* put character on USART (non-blocking until buffer is full) */
|
||||
void usart_putchar_nonblocking(char c)
|
||||
{
|
||||
while (tx_used>=sizeof(tx_buffer)) { // idle until buffer has some space
|
||||
@ -123,14 +121,9 @@ void usart_putchar_nonblocking(char c)
|
||||
usart_enable_tx_interrupt(USART); // enable transmit interrupt
|
||||
}
|
||||
|
||||
#if (USART==USART1)
|
||||
void usart1_isr(void)
|
||||
#elif (USART==USART2)
|
||||
void usart2_isr(void)
|
||||
#elif (USART==USART3)
|
||||
void usart3_isr(void)
|
||||
#endif
|
||||
{ // USART interrupt
|
||||
/** @brief USART interrupt service routine called when data has been transmitted or received */
|
||||
void USART_ISR(void)
|
||||
{
|
||||
if (usart_get_interrupt_source(USART, USART_SR_TXE)) { // data has been transmitted
|
||||
if (!tx_used) { // no data in the buffer to transmit
|
||||
usart_disable_tx_interrupt(USART); // disable transmit interrupt
|
||||
|
33
lib/usart.h
33
lib/usart.h
@ -12,21 +12,36 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
/* Copyright (c) 2016 King Kévin <kingkevin@cuvoodoo.info> */
|
||||
/* this library handles USART communication */
|
||||
/* peripherals used: USART (check source for details) */
|
||||
/** @brief library for USART communication (API)
|
||||
* @file usart.h
|
||||
* @author King Kévin <kingkevin@cuvoodoo.info>
|
||||
* @date 2016
|
||||
* @note peripherals used: USART @ref usart
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/* show the user how much received is available */
|
||||
/** transmit and receive buffer sizes */
|
||||
#define USART_BUFFER 128
|
||||
/** how many bytes available in the received buffer since last read */
|
||||
extern volatile uint8_t usart_received;
|
||||
|
||||
/* setup USART port */
|
||||
/** @brief setup USART peripheral */
|
||||
void usart_setup(void);
|
||||
/* put character on USART (blocking) */
|
||||
/** @brief send character over USART (blocking)
|
||||
* @param[in] c character to send
|
||||
* @note blocks until character transmission started */
|
||||
void usart_putchar_blocking(char c);
|
||||
/* ensure all data has been transmitted (blocking) */
|
||||
/** @brief ensure all data has been transmitted (blocking)
|
||||
* @note block until all data has been transmitted
|
||||
*/
|
||||
void usart_flush(void);
|
||||
/* get character from USART (blocking) */
|
||||
/** @brief get character received over USART (blocking)
|
||||
* @return character received over USART
|
||||
* @note blocks until character is received over USART when received buffer is empty
|
||||
*/
|
||||
char usart_getchar(void);
|
||||
/* put character on USART (non-blocking until buffer is full) */
|
||||
/** @brief send character over USART (non-blocking)
|
||||
* @param[in] c character to send
|
||||
* @note blocks if transmit buffer is full, else puts in buffer and returns
|
||||
*/
|
||||
void usart_putchar_nonblocking(char c);
|
||||
|
@ -12,8 +12,11 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
/* Copyright (c) 2016 King Kévin <kingkevin@cuvoodoo.info> */
|
||||
/* this library handles the USB CDC ACM */
|
||||
/** @brief library for USB CDC ACM communication (code)
|
||||
* @file usb_cdcacm.c
|
||||
* @author King Kévin <kingkevin@cuvoodoo.info>
|
||||
* @date 2016
|
||||
*/
|
||||
|
||||
/* standard libraries */
|
||||
#include <stdint.h> // standard integer types
|
||||
@ -31,8 +34,8 @@
|
||||
|
||||
#include "usb_cdcacm.h" // USB CDC ACM header and definitions
|
||||
|
||||
/* USB devices descriptor
|
||||
* as defined in USB CDC specification section 5
|
||||
/** @brief USB CDC ACM device descriptor
|
||||
* @note as defined in USB CDC specification section 5
|
||||
*/
|
||||
static const struct usb_device_descriptor device_descriptor = {
|
||||
.bLength = USB_DT_DEVICE_SIZE, // the size of this header in bytes, 18
|
||||
@ -51,6 +54,9 @@ static const struct usb_device_descriptor device_descriptor = {
|
||||
.bNumConfigurations = 1, // the number of possible configurations this device has
|
||||
};
|
||||
|
||||
/** @brief USB CDC ACM data endpoints
|
||||
* @note as defined in USB CDC specification section 5
|
||||
*/
|
||||
static const struct usb_endpoint_descriptor data_endpoints[] = {{
|
||||
.bLength = USB_DT_ENDPOINT_SIZE, // the size of the endpoint descriptor in bytes
|
||||
.bDescriptorType = USB_DT_ENDPOINT, // a value of 5 indicates that this describes an endpoint
|
||||
@ -67,9 +73,8 @@ static const struct usb_endpoint_descriptor data_endpoints[] = {{
|
||||
.bInterval = 1, // the frequency, in number of frames, that we're going to be sending data
|
||||
}};
|
||||
|
||||
/* This notification endpoint isn't implemented. According to CDC spec its
|
||||
* optional, but its absence causes a NULL pointer dereference in Linux
|
||||
* cdc_acm driver.
|
||||
/** @brief USB CDC ACM communication endpoints
|
||||
* @note This notification endpoint isn't implemented. According to CDC spec its optional, but its absence causes a NULL pointer dereference in Linux cdc_acm driver
|
||||
*/
|
||||
static const struct usb_endpoint_descriptor communication_endpoints[] = {{
|
||||
.bLength = USB_DT_ENDPOINT_SIZE, // the size of the endpoint descriptor in bytes
|
||||
@ -80,8 +85,8 @@ static const struct usb_endpoint_descriptor communication_endpoints[] = {{
|
||||
.bInterval = 255, // the frequency, in number of frames, that we're going to be sending data
|
||||
}};
|
||||
|
||||
/* functional descriptor
|
||||
* as defined in USB CDC specification section 5.2.3
|
||||
/** @brief USB CDC ACM functional descriptor
|
||||
* @note as defined in USB CDC specification section 5.2.3
|
||||
*/
|
||||
static const struct {
|
||||
struct usb_cdc_header_descriptor header;
|
||||
@ -117,8 +122,8 @@ static const struct {
|
||||
},
|
||||
};
|
||||
|
||||
/* communication class interface descriptor
|
||||
* as defined in USB CDC specification section 5.1.3
|
||||
/** @brief USB CDC interface descriptor
|
||||
* @note as defined in USB CDC specification section 5.1.3
|
||||
*/
|
||||
static const struct usb_interface_descriptor communication_interface[] = {{
|
||||
.bLength = USB_DT_INTERFACE_SIZE,
|
||||
@ -137,8 +142,8 @@ static const struct usb_interface_descriptor communication_interface[] = {{
|
||||
.extralen = sizeof(cdcacm_functional_descriptors),
|
||||
}};
|
||||
|
||||
/* data class interface descriptor
|
||||
* as defined in USB CDC specification section 5.1.3
|
||||
/** @brief USB CDC ACM data class interface descriptor
|
||||
* @note as defined in USB CDC specification section 5.1.3
|
||||
*/
|
||||
static const struct usb_interface_descriptor data_interface[] = {{
|
||||
.bLength = USB_DT_INTERFACE_SIZE,
|
||||
@ -154,6 +159,7 @@ static const struct usb_interface_descriptor data_interface[] = {{
|
||||
.endpoint = data_endpoints,
|
||||
}};
|
||||
|
||||
/** @brief USB CDC ACM interface descriptor */
|
||||
static const struct usb_interface interfaces[] = {{
|
||||
.num_altsetting = 1,
|
||||
.altsetting = communication_interface,
|
||||
@ -162,6 +168,7 @@ static const struct usb_interface interfaces[] = {{
|
||||
.altsetting = data_interface,
|
||||
}};
|
||||
|
||||
/** @brief USB CDC ACM configuration descriptor */
|
||||
static const struct usb_config_descriptor config = {
|
||||
.bLength = USB_DT_CONFIGURATION_SIZE, // the length of this header in bytes
|
||||
.bDescriptorType = USB_DT_CONFIGURATION, // a value of 2 indicates that this is a configuration descriptor
|
||||
@ -175,17 +182,19 @@ static const struct usb_config_descriptor config = {
|
||||
.interface = interfaces, // pointer to an array of interfaces
|
||||
};
|
||||
|
||||
/* string table (starting with index 1) */
|
||||
const char *usb_strings[] = {
|
||||
/** @brief USB string table
|
||||
* @note starting with index 1
|
||||
*/
|
||||
static const char *usb_strings[] = {
|
||||
"CuVoodoo",
|
||||
"CDC-ACM",
|
||||
"STM32F1",
|
||||
};
|
||||
|
||||
/* buffer to be used for control requests */
|
||||
/** buffer to be used for control requests */
|
||||
static uint8_t usbd_control_buffer[128];
|
||||
|
||||
/* structure holding all the info related to the USB device */
|
||||
/** structure holding all the info related to the USB device */
|
||||
static usbd_device *usb_device;
|
||||
|
||||
/* input and output ring buffer, indexes, and available memory */
|
||||
@ -195,10 +204,9 @@ static volatile uint8_t rx_used = 0;
|
||||
static uint8_t tx_buffer[CDCACM_BUFFER] = {0};
|
||||
static volatile uint8_t tx_i = 0;
|
||||
static volatile uint8_t tx_used = 0;
|
||||
/* show the user how much data received over USB is ready */
|
||||
volatile uint8_t cdcacm_received = 0; // same as rx_used, but since the user can write this variable we don't rely on it
|
||||
|
||||
/* disconnect USB by pulling down D+ to for re-enumerate */
|
||||
/** @brief disconnect USB by pulling down D+ to for re-enumerate */
|
||||
static void usb_disconnect(void)
|
||||
{
|
||||
/* short USB disconnect to force re-enumerate */
|
||||
@ -222,6 +230,9 @@ static void usb_disconnect(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
/** @brief incoming USB CDC ACM control request
|
||||
* @note resets device when configured with 5 bits
|
||||
*/
|
||||
static int cdcacm_control_request(usbd_device *usbd_dev, struct usb_setup_data *req, uint8_t **buf, uint16_t *len, void (**complete)(usbd_device *usbd_dev, struct usb_setup_data *req))
|
||||
{
|
||||
(void)complete;
|
||||
@ -338,7 +349,6 @@ void cdcacm_setup(void)
|
||||
usbd_ep_write_packet(usb_device, 0x82, NULL, 0);
|
||||
}
|
||||
|
||||
/* get character from USB CDC ACM (blocking) */
|
||||
char cdcacm_getchar(void)
|
||||
{
|
||||
while (!rx_used) { // idle until data is available
|
||||
@ -351,7 +361,6 @@ char cdcacm_getchar(void)
|
||||
return to_return;
|
||||
}
|
||||
|
||||
/* put character on USB CDC ACM (blocking) */
|
||||
void cdcacm_putchar(char c)
|
||||
{
|
||||
if (tx_used<sizeof(tx_buffer)) { // buffer not full
|
||||
@ -364,10 +373,12 @@ void cdcacm_putchar(char c)
|
||||
usbd_ep_write_packet(usb_device, 0x82, NULL, 0); // trigger tx (not sure why cdcacm_data_tx_cb doesn't work else)
|
||||
}
|
||||
|
||||
/** @brief USB interrupt service routine called on wake-up event */
|
||||
void usb_wakeup_isr(void) {
|
||||
usbd_poll(usb_device);
|
||||
}
|
||||
|
||||
/** @brief USB interrupt service routine called when data is received */
|
||||
void usb_lp_can_rx0_isr(void) {
|
||||
usbd_poll(usb_device);
|
||||
}
|
||||
|
@ -12,18 +12,27 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
/* Copyright (c) 2016 King Kévin <kingkevin@cuvoodoo.info> */
|
||||
/* this library handles the USB CDC ACM */
|
||||
/** @brief library for USB CDC ACM communication (API)
|
||||
* @file usb_cdcacm.h
|
||||
* @author King Kévin <kingkevin@cuvoodoo.info>
|
||||
* @date 2016
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/* RX buffer size */
|
||||
/** transmit and receive buffer sizes */
|
||||
#define CDCACM_BUFFER 128
|
||||
/* show the user how much received is available */
|
||||
/** how many bytes available in the received buffer since last read */
|
||||
extern volatile uint8_t cdcacm_received;
|
||||
|
||||
/* setup USB CDC ACM */
|
||||
/** @brief setup USB CDC ACM peripheral */
|
||||
void cdcacm_setup(void);
|
||||
/* get character from USB CDC ACM (blocking) */
|
||||
/** @brief get character received over USB (blocking)
|
||||
* @return character received over USB
|
||||
* @note blocks until character is received over USB when received buffer is empty
|
||||
*/
|
||||
char cdcacm_getchar(void);
|
||||
/* put character on USB CDC ACM (blocking) */
|
||||
/** @brief send character over USB (non-blocking)
|
||||
* @param[in] c character to send
|
||||
* @note blocks if transmit buffer is full, else puts in buffer and returns
|
||||
*/
|
||||
void cdcacm_putchar(char c);
|
||||
|
24
main.c
24
main.c
@ -13,11 +13,12 @@
|
||||
*
|
||||
*/
|
||||
/** @file main.c
|
||||
* @author King Kévin <kingkevin@cuvoodoo.info>
|
||||
* @date 2016
|
||||
* @brief show the time on a LED strip
|
||||
* the LED strip consists of 60 WS2812b LEDs
|
||||
* the time is read from a DS1307 RTC module
|
||||
@author King Kévin <kingkevin@cuvoodoo.info>
|
||||
@date 2016
|
||||
@brief show the time on a LED strip
|
||||
|
||||
The LED strip consists of 60 WS2812b LEDs.
|
||||
The time is read from a DS1307 RTC module.
|
||||
*/
|
||||
|
||||
/* standard libraries */
|
||||
@ -42,8 +43,11 @@
|
||||
#include "led_ws2812b.h" // WS2812b LEDs utilities
|
||||
#include "rtc_ds1307.h" // Real Time Clock DS1307 utilities
|
||||
|
||||
/* flag set in interrupts to be processed in main task */
|
||||
volatile bool button_flag = false; // button has been pressed
|
||||
/** @defgroup main_flags flag set in interrupts to be processed in main task
|
||||
@{
|
||||
*/
|
||||
volatile bool button_flag = false; /**< flag set if board user button has been pressed */
|
||||
/** @} */
|
||||
|
||||
/** the number of ticks in one second
|
||||
* @note the other values are derived from this value @ref main_ticks
|
||||
@ -63,7 +67,8 @@ const uint32_t ticks_hour = 60*60*TICKS_PER_SECOND;
|
||||
const uint32_t ticks_midday = 12*60*60*TICKS_PER_SECOND;
|
||||
/** @} */
|
||||
|
||||
uint8_t clock_leds[WS2812B_LEDS*3] = {0}; // RGB values for the WS2812b clock LEDs
|
||||
/** RGB values for the WS2812b clock LEDs */
|
||||
uint8_t clock_leds[WS2812B_LEDS*3] = {0};
|
||||
|
||||
/** @brief default printf output */
|
||||
int _write(int file, char *ptr, int len)
|
||||
@ -215,6 +220,9 @@ static void leds_set(void)
|
||||
}
|
||||
}
|
||||
|
||||
/** @brief program entry point
|
||||
* this is the firmware function started by the micro-controller
|
||||
*/
|
||||
int main(void)
|
||||
{
|
||||
SCB_VTOR = (uint32_t) 0x08002000; // relocate vector table because of the bootloader
|
||||
|
Loading…
Reference in New Issue
Block a user