From 54e9f8d2af25b11710e86886f09b07975bd3e9cc Mon Sep 17 00:00:00 2001 From: Rutherther Date: Wed, 18 Dec 2024 23:34:37 +0100 Subject: [PATCH] feat(arm07): implement most --- arm06/src/main.c | 2 +- arm07/.envrc | 2 +- arm07/include/buffered_peripheral.h | 8 +- arm07/include/queue.h | 4 +- arm07/include/spi.h | 13 +- arm07/include/spi_matrix.h | 4 +- arm07/include/timer.h | 9 +- arm07/include/uart.h | 2 + arm07/picocom.sh | 2 +- arm07/src/buffered_peripheral.c | 19 +- arm07/src/main.c | 502 +++++++++++++++++++++------- arm07/src/queue.c | 3 +- arm07/src/spi.c | 41 ++- arm07/src/spi_matrix.c | 17 +- arm07/src/timer.c | 28 +- arm07/src/uart.c | 22 +- 16 files changed, 516 insertions(+), 162 deletions(-) diff --git a/arm06/src/main.c b/arm06/src/main.c index cb11cf1..b634284 100644 --- a/arm06/src/main.c +++ b/arm06/src/main.c @@ -221,7 +221,7 @@ void main() } } - usart_transmit(&uart, " V\r\n", 4); + usart_transmit(&uart, " V (averaged)\r\n", 15); } } diff --git a/arm07/.envrc b/arm07/.envrc index 6370a6b..d0c47f2 100644 --- a/arm07/.envrc +++ b/arm07/.envrc @@ -1,4 +1,4 @@ use guix # This is for clangd to work, it doesn't respect CROSS_C_INCLUDE_PATH. -export C_INCLUDE_PATH=$CROSS_C_INCLUDE_PATH +export C_INCLUDE_PATH=$CROSS_C_INCLUDE_PATH:$C_INCLUDE_PATH diff --git a/arm07/include/buffered_peripheral.h b/arm07/include/buffered_peripheral.h index f30fe03..5cb48d6 100644 --- a/arm07/include/buffered_peripheral.h +++ b/arm07/include/buffered_peripheral.h @@ -8,13 +8,13 @@ typedef bool (*transceiver_can_receive_t)(void* peripheral); typedef bool (*transceiver_can_transmit_t)(void* peripheral); -typedef bool (*transceiver_receive_t)(void* peripheral, void* buffer, uint16_t max_size); -typedef bool (*transceiver_transmit_t)(void* peripheral, void* data, uint16_t size); +typedef uint16_t (*transceiver_receive_t)(void* peripheral, void* buffer, uint16_t max_size); +typedef uint16_t (*transceiver_transmit_t)(void* peripheral, void* data, uint16_t size); typedef enum { OK, WOULD_BLOCK, - ERROR, + TASK_ERROR, } task_result_t; typedef struct { @@ -45,6 +45,6 @@ uint16_t buffered_transceiver_receive(buffered_transceiver_t* transceiver, void buffered_transceiver_trigger_receive(buffered_transceiver_t* transceiver, uint16_t size); -void buffered_transceiver_trigger_transmit(buffered_transceiver_t* transceiver, uint16_t size); +bool buffered_transceiver_trigger_transmit(buffered_transceiver_t* transceiver, uint16_t size); #endif // BUFFERED_PERIPHERAL_H diff --git a/arm07/include/queue.h b/arm07/include/queue.h index 8a06ca7..2206cff 100644 --- a/arm07/include/queue.h +++ b/arm07/include/queue.h @@ -13,7 +13,7 @@ typedef struct { atomic_uint_least16_t curr_write_ptr; atomic_uint_least16_t space; - uint8_t elements[0]; + uint8_t* elements; } queue_t; /** @@ -31,7 +31,7 @@ queue_t* queue_malloc(uint16_t element_size, uint16_t length); * @param[in] element_size The size of one element. * @param[in] length The maximum number of elements. */ -void queue_init(queue_t* queue, uint16_t element_size, uint16_t length); +void queue_init(queue_t* queue, uint16_t element_size, uint16_t length, void* data); /** * @brief Enqueue the given element to the queue. diff --git a/arm07/include/spi.h b/arm07/include/spi.h index 4405a11..77aaedf 100644 --- a/arm07/include/spi.h +++ b/arm07/include/spi.h @@ -4,6 +4,7 @@ #include #include #include +#include "pin.h" typedef enum { SPI_FRAME_8_BIT = 0, @@ -18,9 +19,10 @@ typedef enum { typedef struct { SPI_TypeDef* periph; uint8_t idx; + pin_t csn; } spi_t; -void spi_init(spi_t* spi, SPI_TypeDef* peripheral, uint8_t idx); +void spi_init(spi_t* spi, pin_t csn, SPI_TypeDef* peripheral, uint8_t idx); void spi_master_configure_speed(spi_t *spi, uint8_t divider); @@ -29,13 +31,14 @@ void spi_master_configure(spi_t *spi, bool sw_nss, bool clock_polarity, bool clock_phase, spi_frame_orientation_t orientation, spi_frame_format_t format); void spi_master_enable(spi_t* spi, bool enable); -void spi_configure_receiver(spi_t* spi, bool enable); -void spi_configure_transmitter(spi_t* spi, bool enable); - uint16_t spi_transmit(spi_t* spi, uint16_t* data, uint16_t size); uint16_t spi_receive(spi_t *spi, uint16_t *buffer, uint16_t max_size); bool spi_can_transmit(spi_t* spi); -bool spi_can_receive(spi_t* spi); +uint16_t spi_can_receive(spi_t* spi); + +void spi_pulse_csn(spi_t *spi); + +bool spi_enable_interrupt(spi_t* spi, bool tx, bool rx); #endif // SPI_H diff --git a/arm07/include/spi_matrix.h b/arm07/include/spi_matrix.h index 0e78c5d..531a970 100644 --- a/arm07/include/spi_matrix.h +++ b/arm07/include/spi_matrix.h @@ -25,8 +25,8 @@ typedef enum { MATRIX_REG_DECODE_MODE = 9, MATRIX_REG_INTENSITY = 10, MATRIX_REG_SCAN_LIMIT = 11, - MATRIX_REG_SHUTDOWN = 11, - MATRIX_REG_DISPLAY_TEST = 11, + MATRIX_REG_SHUTDOWN = 12, + MATRIX_REG_DISPLAY_TEST = 13, } matrix_register_t; typedef struct { diff --git a/arm07/include/timer.h b/arm07/include/timer.h index 5d27e00..41c782c 100644 --- a/arm07/include/timer.h +++ b/arm07/include/timer.h @@ -1,4 +1,5 @@ #include +#include #ifndef TIMER_H #define TIMER_H @@ -33,9 +34,11 @@ void timer_master_mode(timer_t* timer, timer_master_mode_t mode); uint16_t timer_count(timer_t* timer); -void timer_enable_interrupt(timer_t* timer); +void timer_enable_interrupt(timer_t *timer, bool update, bool capture1); void timer_disable_interrupt(timer_t* timer); -uint32_t timer_is_interrupt(timer_t* timer); -void timer_clear_interrupt(timer_t* timer); +uint32_t timer_is_update_interrupt(timer_t* timer); +uint32_t timer_is_capture1_interrupt(timer_t *timer); +void timer_clear_capture1_interrupt(timer_t* timer); +void timer_clear_update_interrupt(timer_t* timer); #endif // TIMER_H diff --git a/arm07/include/uart.h b/arm07/include/uart.h index f35d951..a22b8f8 100644 --- a/arm07/include/uart.h +++ b/arm07/include/uart.h @@ -46,4 +46,6 @@ uint16_t usart_receive(uart_t* uart, char* buffer, uint16_t max_size); bool usart_can_transmit(uart_t* uart); uint16_t usart_can_receive(uart_t* uart); +void usart_enable_interrupt(uart_t* uart, bool tx, bool rx); + #endif // UART_H diff --git a/arm07/picocom.sh b/arm07/picocom.sh index 8540d7d..b6944cf 100755 --- a/arm07/picocom.sh +++ b/arm07/picocom.sh @@ -1,2 +1,2 @@ #!/usr/bin/env bash -picocom "$1" --stopbits 1 --databits 8 --parity e --baud 9600 --echo --omap crlf +picocom "$1" --stopbits 1 --databits 8 --parity e --baud 9600 --omap crlf diff --git a/arm07/src/buffered_peripheral.c b/arm07/src/buffered_peripheral.c index 8fac5c7..8358d07 100644 --- a/arm07/src/buffered_peripheral.c +++ b/arm07/src/buffered_peripheral.c @@ -1,5 +1,6 @@ #include "buffered_peripheral.h" #include +#include void buffered_transceiver_init(buffered_transceiver_t *transceiver, queue_t *rx_queue, queue_t *tx_queue, @@ -14,6 +15,10 @@ uint16_t buffered_transceiver_transmit(buffered_transceiver_t *transceiver, void *buffer, uint16_t size) { uint16_t sent = 0; + if (size == 0) { + size = strlen((char*)buffer); + } + while (sent < size && queue_space(transceiver->tx_queue) > 0) { queue_enqueue(transceiver->tx_queue, buffer + sent * transceiver->tx_queue->element_size); sent++; @@ -30,7 +35,7 @@ uint16_t buffered_transceiver_receive(buffered_transceiver_t *transceiver, buffered_transceiver_trigger_receive(transceiver, 1); uint16_t received = 0; - while (queue_count(transceiver->rx_queue) > 0) { + while (received < max_size && queue_count(transceiver->rx_queue) > 0) { queue_dequeue_safely(transceiver->rx_queue, buffer + received*transceiver->rx_queue->element_size); received++; } @@ -42,17 +47,23 @@ void buffered_transceiver_trigger_receive(buffered_transceiver_t *transceiver, u void* element = alloca(transceiver->rx_queue->element_size); while (transceiver->vtable.can_receive(transceiver->peripheral) > 0 && queue_space(transceiver->rx_queue) > 0) { - transceiver->vtable.receive(transceiver->peripheral, &element, 1); - queue_enqueue(transceiver->rx_queue, &element); + uint16_t received = transceiver->vtable.receive(transceiver->peripheral, element, 1); + + if (received > 0) { + queue_enqueue(transceiver->rx_queue, element); + } } } -void buffered_transceiver_trigger_transmit(buffered_transceiver_t *transceiver, +bool buffered_transceiver_trigger_transmit(buffered_transceiver_t *transceiver, uint16_t size) { while (transceiver->vtable.can_transmit(transceiver->peripheral) && queue_count(transceiver->tx_queue) > 0) { void* data = alloca(transceiver->tx_queue->element_size); queue_dequeue_safely(transceiver->tx_queue, data); transceiver->vtable.transmit(transceiver->peripheral, data, 1); + return true; } + + return false; } diff --git a/arm07/src/main.c b/arm07/src/main.c index b3b7f28..10ec593 100644 --- a/arm07/src/main.c +++ b/arm07/src/main.c @@ -9,7 +9,9 @@ #include "display.h" #include "delay.h" #include "uart.h" -#include "adc.h" +#include "spi.h" +#include "buffered_peripheral.h" +#include "spi_matrix.h" void hard_fault_handler() { while(1) {} @@ -69,29 +71,172 @@ void SystemCoreClockSetHSI(void) { while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); // Wait till PLL is system clock src } -#define DIGITS 4 +#define COMMAND_SEPARATOR '\n' -#define ADC_MEASUREMENTS 16 -#define LOG2_ADC_MEASUREMENTS 4 -uint16_t adc_stored_values[ADC_MEASUREMENTS * 2]; +// Button +pin_t user_button; +timer_t button_timer; +exti_t button_exti; -display_t display; -timer_t display_timer; +// Display +matrix_t matrix; +timer_t matrix_timer; + +// SPI +pin_t spi_csn; +spi_t matrix_spi; +buffered_transceiver_t matrix_tx; +timer_t spi_csn_timer; + +// Uart uart_t uart; -adc_t adc; -timer_t adc_timer; +buffered_transceiver_t uart_rx; + +#define MAX_CMD_LENGTH 65 + +#define AUTO_TOGGLE_CYCLES 1000000 +#define MAX_IMAGES 10 + +uint8_t images_count = 4; +uint8_t current_image = 0; +uint8_t images[MAX_IMAGES][8] = { + {0b11111111, 0b10000001, 0b10000001, 0b10000001, 0b10000001, 0b10000001, 0b10000001, 0b11111111}, + { 0b00000100, 0b00001110, 0b11110001, 0b10000101, 0b10000001, 0b10110001, 0b10110001, 0b11111111 }, + { 0b11111000, 0b11100100, 0b11100010, 0b10000001, 0b10000001, 0b01000010, 0b00100100, 0b00011000 }, + { 0b11000000, 0b10011000, 0b11010000, 0b10011010, 0b10010010, 0b00011010, 0b00000010, 0b00000011 }, +}; + +uint32_t cycle = 0; +bool auto_toggle = false; +bool toggle_next = false; + +bool animation = false; + +void handle_command(char* cmd, uint16_t len) { + if (len == 0) { + return; + } + + bool handled = false; + + switch (cmd[0]) { + case 'n': + // next + if (len == 1) { + handled = true; + toggle_next = true; + buffered_transceiver_transmit(&uart_rx, "Switching to next image.\r\n", 0); + } + break; + case 'N': + // auto toggle + if (len == 1) { + auto_toggle = !auto_toggle; + + if (auto_toggle) { + buffered_transceiver_transmit(&uart_rx, "Going to toggle automatically.\r\n", 0); + } else { + buffered_transceiver_transmit(&uart_rx, "Manual switch mode.\r\n", 0); + } + } + break; + case 'a': + // animate + if (len == 1) { + handled = true; + animation = !animation; + + if (animation) { + buffered_transceiver_transmit(&uart_rx, "Animation enabled.\r\n", 0); + } else { + buffered_transceiver_transmit(&uart_rx, "Animation disabled.\r\n", 0); + } + } + break; + case 'u': + // upload + // TODO + break; + case 's': + // number of slots is... + // TODO + break; + + default: + break; + } + + if (!handled) { + buffered_transceiver_transmit(&uart_rx, "Unknown command!\r\n", 0); + } +} + +char* receive_command(uint16_t* length) +{ + static char cmd[MAX_CMD_LENGTH]; + static uint16_t index; + + char* current_char = (cmd + index); + + while (buffered_transceiver_receive(&uart_rx, current_char, 1) == 1) { + // echo + buffered_transceiver_transmit(&uart_rx, current_char, 1); -typedef struct { - char digits[4]; - uint8_t digits_count; - uint8_t dot; - bool error; -} converted_number_t; + if (*current_char == COMMAND_SEPARATOR) { + buffered_transceiver_transmit(&uart_rx, "\r", 1); + *current_char = '\0'; + *length = index; + index = 0; + return cmd; + } + + index++; + } + + // Commands are separated either through max length, or by new line + if (index == MAX_CMD_LENGTH + 1) { + *length = MAX_CMD_LENGTH; + index = 0; + return cmd; + } + + return NULL; +} + +void next_image() +{ + current_image++; + current_image %= images_count; + + matrix_set_buffer(&matrix, MATRIX_SLOT_OTHER, &images[current_image][0]); + + if (animation) { + matrix_animate_swap(&matrix); + } else { + matrix_swap(&matrix); + } +} + +void app_loop() +{ + while (1) { + if (auto_toggle && cycle >= AUTO_TOGGLE_CYCLES) { + next_image(); + cycle = 0; + } else if (toggle_next) { + next_image(); + toggle_next = false; + } -converted_number_t convert_number(char* data); + uint16_t command_len; + char* cmd = receive_command(&command_len); + if (cmd != NULL) { + handle_command(cmd, command_len); + } -uint32_t averaged_adc_value = 0; -bool updated_average = 0; + cycle++; + } +} void main() { @@ -99,45 +244,37 @@ void main() SystemCoreClockSetHSI(); systick_configure(); - RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOCEN | RCC_AHB1ENR_DMA2EN; - RCC->APB1ENR |= RCC_APB1ENR_TIM3EN | RCC_APB1ENR_USART2EN | RCC_APB1ENR_TIM2EN; - RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN | RCC_APB2ENR_ADC1EN; + RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOCEN; + RCC->APB1ENR |= RCC_APB1ENR_TIM3EN | RCC_APB1ENR_TIM4EN | RCC_APB1ENR_USART2EN | RCC_APB1ENR_TIM2EN; + RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN | RCC_APB2LPENR_SPI1LPEN; - // The timer clocks are at 12 MHz. - // For 100 Hz, the prescaler would be 120 000. That is too big, - // so 200 Hz is chosen. From there it will have to be divided by 2 by application. - // For 6800 Hz, 1765 prescaler will be used, leading to 6798... Hz + { // UART init + pin_t pin_rx; + pin_t pin_tx; - // Initialize timer for display at interrupt frequency - // digit update frequency * digits * 34 - // aim for 100 Hz * 4 * 17 = 6 800 Hz + #define UART_RX_BUFFER_SIZE 32 + #define UART_TX_BUFFER_SIZE 32 - { - pin_t pin_data; - pin_t pin_sftclk; - pin_t pin_strobe; + static queue_t uart_rx_queue, uart_tx_queue; + static uint16_t uart_rx_buffer[UART_RX_BUFFER_SIZE], uart_tx_buffer[UART_TX_BUFFER_SIZE]; - pin_init(&pin_data, GPIOA, 9); - pin_init(&pin_sftclk, GPIOA, 8); - pin_init(&pin_strobe, GPIOB, 5); + queue_init(&uart_rx_queue, sizeof(char), UART_RX_BUFFER_SIZE, uart_rx_buffer); + queue_init(&uart_tx_queue, sizeof(char), UART_TX_BUFFER_SIZE, uart_tx_buffer); - pin_into_output(&pin_data); - pin_into_output(&pin_sftclk); - pin_into_output(&pin_strobe); + bool usart_generic_can_receive(void* peripheral); + bool usart_generic_can_transmit(void* peripheral); - display_init(&display, DIGITS, pin_data, pin_sftclk, pin_strobe); - display_dots(&display, 1 << 0); + uint16_t usart_generic_receive(void* peripheral, void* buffer, uint16_t max_size); + uint16_t usart_generic_transmit(void* peripheral, void* data, uint16_t size); - timer_init(&display_timer, TIM3, 3); - timer_configure(&display_timer, 0, 500, 0); - timer_set_refresh(&display_timer, 4); - timer_enable_interrupt(&display_timer); - timer_enable(&display_timer); - } + buffered_transceiver_vtable_t vtable = { + .can_receive = usart_generic_can_receive, + .can_transmit = usart_generic_can_transmit, + .transmit = usart_generic_transmit, + .receive = usart_generic_receive, + }; - { - pin_t pin_rx; - pin_t pin_tx; + buffered_transceiver_init(&uart_rx, &uart_rx_queue, &uart_tx_queue, &uart, vtable); pin_init(&pin_tx, GPIOA, 2); pin_init(&pin_rx, GPIOA, 3); @@ -149,108 +286,241 @@ void main() usart_configure_speed(&uart, 12000000, 9600); usart_configure_uart(&uart, true, USART_WORD_9_BITS, true, USART_PARITY_EVEN, USART_STOP_BIT_ONE); + usart_enable_interrupt(&uart, false, true); usart_configure_transmitter(&uart, true); usart_configure_receiver(&uart, true); } - __enable_irq(); + { // SPI init + pin_t pin_mosi; + pin_t pin_csn; + pin_t pin_clk; - // Application - while (1) { - if (!updated_average) { - continue; - } - updated_average = false; + #define SPI_RX_BUFFER_SIZE 1 + #define SPI_TX_BUFFER_SIZE 10 - uint32_t value = averaged_adc_value; - uint32_t voltage = (value * 3300) / 4096; + static queue_t spi_rx_queue, spi_tx_queue; + static uint16_t spi_rx_buffer[SPI_RX_BUFFER_SIZE], spi_tx_buffer[SPI_TX_BUFFER_SIZE]; - display_convert_number(&display, voltage); - for (uint8_t digit = 0; digit < display.digits_count; digit++) { - usart_transmit(&uart, &display.digits[digit], 1); + queue_init(&spi_rx_queue, sizeof(uint16_t), SPI_RX_BUFFER_SIZE, spi_rx_buffer); + queue_init(&spi_tx_queue, sizeof(uint16_t), SPI_TX_BUFFER_SIZE, spi_tx_buffer); - if (digit == 0) { - usart_transmit(&uart, ".", 1); - } - } + bool spi_generic_can_receive(void* peripheral); + bool spi_generic_can_transmit(void* peripheral); - usart_transmit(&uart, " V\r\n", 4); - } -} + uint16_t spi_generic_receive(void* peripheral, void* buffer, uint16_t max_size); + uint16_t spi_generic_transmit(void* peripheral, void* data, uint16_t size); -converted_number_t convert_number(char* data) { - converted_number_t number; - bool found_dot = false; - uint8_t curr_digit = 0; + buffered_transceiver_vtable_t vtable = { + .can_receive = spi_generic_can_receive, + .can_transmit = spi_generic_can_transmit, + .transmit = spi_generic_transmit, + .receive = spi_generic_receive, + }; - number.dot = 0; - number.error = false; + buffered_transceiver_init(&matrix_tx, &spi_rx_queue, &spi_tx_queue, &matrix_spi, vtable); - while (*data != '\0' && curr_digit < DIGITS) { - char curr = *(data++); + pin_init(&pin_mosi, GPIOA, 7); + pin_init(&pin_csn, GPIOA, 4); + pin_init(&pin_clk, GPIOB, 3); - // handle first dot - if (curr == '.' && !found_dot) { - found_dot = true; + pin_into_alternate(&pin_mosi, 5); + /* pin_into_alternate(&pin_csn, 5); */ + pin_into_alternate(&pin_clk, 5); - // if dot first, assume zero. - if (curr_digit == 0) { - number.digits[curr_digit++] = '0'; - } + pin_set(&pin_csn); + pin_into_output_pushpull(&pin_csn); - number.dot = 1 << (curr_digit - 1); - continue; + timer_init(&spi_csn_timer, TIM4, 4); + timer_set_refresh(&spi_csn_timer, 1); + timer_configure(&spi_csn_timer, 0, 10000, 0); + timer_enable_interrupt(&spi_csn_timer, true, false); - // handle digit - } else if (curr >= '0' && curr <= '9') { - number.digits[curr_digit++] = curr; + spi_init(&matrix_spi, pin_csn, SPI1, 1); + spi_master_configure_speed(&matrix_spi, 7); + spi_master_configure(&matrix_spi, false, false, false, + SPI_MSB_FIRST, SPI_FRAME_16_BIT); - // handle others - } else { - number.error = true; - break; - } + spi_enable_interrupt(&matrix_spi, true, false); + spi_master_enable(&matrix_spi, true); + } + { // Matrix, timer init + matrix_init(&matrix, &matrix_tx, 5); + matrix_setup(&matrix); + matrix_enable(&matrix, true); + + matrix_set_buffer(&matrix, MATRIX_SLOT0, images[current_image]); + + timer_init(&matrix_timer, TIM3, 3); + timer_set_refresh(&matrix_timer, 20); + timer_configure(&matrix_timer, 0, 60000, 0); + timer_enable_interrupt(&matrix_timer, true, false); + timer_enable(&matrix_timer); } - if (*data != '\0') { - number.error = true; + { // Button, exti, timer + pin_init(&user_button, GPIOC, 13); + pin_into_input(&user_button); + + exti_init(&button_exti, 13, EXTI, SYSCFG); + exti_external_interrupt(&button_exti, 2); + exti_falling_interrupt(&button_exti); + exti_clear_interrupt(&button_exti); + exti_enable_interrupt(&button_exti); + + timer_init(&button_timer, TIM2, 2); + timer_set_refresh(&button_timer, 9999); + timer_configure(&button_timer, 0, 60000, 1); + + pin_t pin_capture; + pin_init(&pin_capture, GPIOA, 15); + pin_into_alternate(&pin_capture, 1); + + reg_write_bits(&button_timer.periph->CCMR1, + // TI1 on CCR1 no prescaler - capture every event sampling freq = fdts / 32, N = 8 + // fdts = 24 MHz, fsample = 750kHz + (1 << TIM_CCMR1_CC1S_Pos) | (0 << TIM_CCMR1_IC1PSC_Pos) | (0xF << TIM_CCMR1_IC1F_Pos), + TIM_CCMR1_CC1S | TIM_CCMR1_IC1PSC | TIM_CCMR1_IC1F); + reg_write_bits( + &button_timer.periph->CCER, + // enable CC1 falling edge captures + (1 << TIM_CCER_CC1E_Pos) | (1 << TIM_CCER_CC1NP_Pos) | (0 << TIM_CCER_CC1P_Pos), + TIM_CCER_CC1E | TIM_CCER_CC1P | TIM_CCER_CC1NP); + + timer_enable_interrupt(&button_timer, true, true); } - number.digits_count = curr_digit; + __enable_irq(); + + // Application + app_loop(); +} + +void EXTI15_10_handler(void) { + if (exti_is_interrupt(&button_exti)) { + exti_clear_interrupt(&button_exti); - return number; + timer_set_counter(&button_timer, 0); + timer_enable(&button_timer); + } } -/* void TIM2_handler(void) { */ -/* // The stopwatch timer */ -/* } */ +void TIM2_handler(void) { + if (timer_is_update_interrupt(&button_timer)) { + timer_clear_update_interrupt(&button_timer); + } else if (timer_is_capture1_interrupt(&button_timer)) { + uint32_t count = button_timer.periph->CCR1; + timer_clear_capture1_interrupt(&button_timer); + + // 200 Hz => 5 ms + // 50 ms is 10. That means button was really pressed by user, no bouncing + // 2 s is 400 + if (count > 10) { // at least 50 ms + if (count > 400) { // at least 2 s + auto_toggle = !auto_toggle; + } else { // less than 2 s + if (auto_toggle) { + auto_toggle = false; + } + else { + toggle_next = true; + } + } + + // stop the timer + timer_disable(&button_timer); + } + } +} void TIM3_handler(void) { - timer_clear_interrupt(&display_timer); - display_update(&display); + timer_clear_update_interrupt(&matrix_timer); + matrix_update(&matrix, &matrix_tx); } -uint32_t average_adc_values(uint16_t* buffer, uint16_t count) { - uint32_t sum = 0; +// A flag to prevent spi communication, +// to toggle csn high +bool spi_can_transmit_flag = true; - for (uint8_t i = 0; i < count; i++) { - sum += buffer[i] & 0xFFF; +void SPI1_handler(void) { + if (spi_can_receive(&matrix_spi)) { + buffered_transceiver_trigger_receive(&matrix_tx, 1); + } + if (spi_can_transmit(&matrix_spi)) { + // + spi_can_transmit_flag = false; + timer_set_counter(&spi_csn_timer, 0); + timer_enable(&spi_csn_timer); + + // Disable interrupt so cpu is not locked + spi_enable_interrupt(&matrix_spi, false, false); } +} + +void TIM4_handler(void) { + timer_clear_update_interrupt(&spi_csn_timer); + + if (!(matrix_spi.periph->SR & SPI_SR_BSY)) { + // disable and enable spi so that CSN is pulsed. + spi_pulse_csn(&matrix_spi); - return sum >> LOG2_ADC_MEASUREMENTS; + // Allow sending... + spi_can_transmit_flag = true; + + // Disable this timer until transmission is done again + timer_disable(&spi_csn_timer); + + // Transmit only after the pulse. SPI is enabled again. + buffered_transceiver_trigger_transmit(&matrix_tx, 1); + + } } -void DMA2_Stream0_handler(void) { - if (DMA2->LISR & DMA_LISR_HTIF0) { - DMA2->LIFCR = DMA_LIFCR_CHTIF0; - averaged_adc_value = average_adc_values(adc_stored_values, ADC_MEASUREMENTS); - } else if (DMA2->LISR & DMA_LISR_TCIF0) { - DMA2->LIFCR = DMA_LIFCR_CTCIF0; - averaged_adc_value = average_adc_values(adc_stored_values + ADC_MEASUREMENTS, ADC_MEASUREMENTS); +void USART2_handler(void) { + if (usart_can_receive(&uart)) { + buffered_transceiver_trigger_receive(&uart_rx, 1); + } + if (usart_can_transmit(&uart)) { + if (!buffered_transceiver_trigger_transmit(&uart_rx, 1)) { + usart_enable_interrupt(&uart, false, true); + } } - updated_average = true; } -void SPI1_handler(void) { + +bool spi_generic_can_receive(void *peripheral) { + return spi_can_receive((spi_t*)peripheral); +} +bool spi_generic_can_transmit(void *peripheral) { + return spi_can_transmit_flag && (((spi_t*)peripheral)->periph->SR & SPI_SR_BSY) == 0; +} + +uint16_t spi_generic_receive(void *peripheral, void *buffer, + uint16_t max_size) { + return spi_receive((spi_t*)peripheral, buffer, max_size); +} +uint16_t spi_generic_transmit(void *peripheral, void *data, uint16_t size) { + // enable the interrupt so that we can send the rest + uint16_t ret = spi_transmit((spi_t*)peripheral, data, size); + spi_enable_interrupt((spi_t*)peripheral, true, false); + return ret; +} + +bool usart_generic_can_receive(void *peripheral) { + return usart_can_receive((uart_t*)peripheral); +} +bool usart_generic_can_transmit(void *peripheral) { + return usart_can_transmit((uart_t*)peripheral); +} + +uint16_t usart_generic_receive(void *peripheral, void *buffer, + uint16_t max_size) { + return usart_receive((uart_t*)peripheral, buffer, max_size); +} +uint16_t usart_generic_transmit(void *peripheral, void *data, uint16_t size) { + uint16_t ret = usart_transmit((uart_t*)peripheral, data, size); + // enable the interrupt so that we can send the rest + usart_enable_interrupt((uart_t*)peripheral, true, true); + return ret; } diff --git a/arm07/src/queue.c b/arm07/src/queue.c index f595299..823e899 100644 --- a/arm07/src/queue.c +++ b/arm07/src/queue.c @@ -5,12 +5,13 @@ queue_t *queue_malloc(uint16_t element_size, uint16_t length) { return (queue_t*)malloc(sizeof(queue_t) + element_size * length); } -void queue_init(queue_t* queue, uint16_t element_size, uint16_t length) { +void queue_init(queue_t* queue, uint16_t element_size, uint16_t length, void* data) { queue->curr_write_ptr = 0; queue->curr_read_ptr = 0; queue->element_size = element_size; queue->length = length; queue->space = length; + queue->elements = data; } bool queue_enqueue(queue_t *queue, void *element) { diff --git a/arm07/src/spi.c b/arm07/src/spi.c index b6c72bc..a08eb1a 100644 --- a/arm07/src/spi.c +++ b/arm07/src/spi.c @@ -1,9 +1,11 @@ #include "spi.h" #include "registers.h" +#include "stm32f401xe.h" -void spi_init(spi_t* spi, SPI_TypeDef* peripheral, uint8_t idx) { +void spi_init(spi_t* spi, pin_t csn, SPI_TypeDef* peripheral, uint8_t idx) { spi->periph = peripheral; spi->idx = idx; + spi->csn = csn; } void spi_master_configure_speed(spi_t *spi, @@ -16,20 +18,22 @@ void spi_master_configure(spi_t *spi, bool sw_nss, bool clock_polarity, reg_write_bits(&spi->periph->CR1, (sw_nss << SPI_CR1_SSM_Pos) | (format << SPI_CR1_DFF_Pos) | (orientation << SPI_CR1_LSBFIRST_Pos) | - (1 << SPI_CR1_BIDIMODE_Pos) | (1 << SPI_CR1_MSTR_Msk) | - (clock_polarity << SPI_CR1_CPOL_Msk) | (clock_phase << SPI_CR1_CPHA_Msk), + (0 << SPI_CR1_BIDIMODE_Pos) | (1 << SPI_CR1_MSTR_Pos) | + (clock_polarity << SPI_CR1_CPOL_Pos) | (clock_phase << SPI_CR1_CPHA_Pos), SPI_CR1_SSM_Msk | SPI_CR1_DFF_Msk | SPI_CR1_LSBFIRST_Msk | SPI_CR1_BIDIMODE_Msk | SPI_CR1_MSTR_Msk | SPI_CR1_CPOL_Msk | SPI_CR1_CPHA_Msk); + + spi->periph->CR2 |= SPI_CR2_SSOE | (1 << 3); } void spi_master_enable(spi_t *spi, bool enable) { - reg_set_bits(&spi->periph->CR1, SPI_CR1_SPE); + reg_write_bits(&spi->periph->CR1, enable << SPI_CR1_SPE_Pos, SPI_CR1_SPE); } uint16_t spi_transmit(spi_t *spi, uint16_t *data, uint16_t size) { + pin_reset(&spi->csn); for (int16_t i = 0; i < size; i++) { - char byte = *(data++); - - while (!(spi->periph->SR & USART_SR_TXE)); - spi->periph->DR = byte; + while (!(spi->periph->SR & SPI_SR_TXE)); + uint16_t word = *(data++); + spi->periph->DR = word; } return size; @@ -37,18 +41,31 @@ uint16_t spi_transmit(spi_t *spi, uint16_t *data, uint16_t size) { uint16_t spi_receive(spi_t *spi, uint16_t *buffer, uint16_t max_size) { uint16_t size = 0; - while (size < max_size - 1 && (spi->periph->SR & USART_SR_RXNE)) { - *(buffer + (size++)) = (char)(spi->periph->DR & USART_DR_DR_Msk); + while (size < max_size && (spi->periph->SR & SPI_SR_RXNE)) { + *(buffer + (size++)) = (char)(spi->periph->DR & SPI_DR_DR_Msk); } return size; } +void spi_pulse_csn(spi_t *spi) { + pin_set(&spi->csn); +} + bool spi_can_transmit(spi_t *spi) { return (spi->periph->SR & SPI_SR_TXE) != 0; } -bool spi_can_receive(spi_t *spi) { - return (spi->periph->SR & SPI_SR_RXNE) != 0; +uint16_t spi_can_receive(spi_t *spi) { + return ((spi->periph->SR & SPI_SR_RXNE) != 0) ? 1 : 0; +} + +bool spi_enable_interrupt(spi_t *spi, bool tx, bool rx) { + reg_write_bits(&spi->periph->CR2, + (tx << SPI_CR2_TXEIE_Pos) | (rx << SPI_CR2_RXNEIE_Pos), + SPI_CR2_TXEIE | SPI_CR2_RXNEIE); + // TODO: proper irq by idx + NVIC_SetPriority(SPI1_IRQn, 1); + NVIC_EnableIRQ(SPI1_IRQn); } diff --git a/arm07/src/spi_matrix.c b/arm07/src/spi_matrix.c index 1188cb4..89ae279 100644 --- a/arm07/src/spi_matrix.c +++ b/arm07/src/spi_matrix.c @@ -6,6 +6,11 @@ void matrix_init(matrix_t *matrix, buffered_transceiver_t *transceiver, uint32_t shift_period) { matrix->transceiver = transceiver; matrix->shift_period = shift_period; + matrix->slot = MATRIX_SLOT0; + matrix->state = MATRIX_OFF; + + matrix->state_cycle = 0; + matrix->cycle = 0; } void matrix_setup(matrix_t *matrix) { @@ -16,6 +21,11 @@ void matrix_setup(matrix_t *matrix) { void matrix_enable(matrix_t *matrix, bool enable) { matrix->state = MATRIX_STABLE; matrix->slot = MATRIX_SLOT0; + + matrix_send(matrix, MATRIX_REG_SHUTDOWN, enable ? 1 : 0); + matrix_send(matrix, MATRIX_REG_DECODE_MODE, 0); + matrix_send(matrix, MATRIX_REG_INTENSITY, 0x01); + matrix_send(matrix, MATRIX_REG_SCAN_LIMIT, 0x7); } void matrix_send(matrix_t *matrix, matrix_register_t reg, uint8_t value) { @@ -45,9 +55,9 @@ void matrix_swap(matrix_t *matrix) { } void matrix_animate_swap(matrix_t *matrix) { - matrix->state = MATRIX_ANIMATING; matrix->state_cycle = 0; matrix->cycle = 0; + matrix->state = MATRIX_ANIMATING; } void matrix_update(matrix_t *matrix, buffered_transceiver_t *transceiver) { @@ -60,12 +70,13 @@ void matrix_update(matrix_t *matrix, buffered_transceiver_t *transceiver) { for (uint8_t digit = 0; digit < DIGITS; digit++) { matrix_send(matrix, MATRIX_REG_DIGIT0 + digit, 0); } - + break; case MATRIX_STABLE: // send all digits for (uint8_t digit = 0; digit < DIGITS; digit++) { matrix_send(matrix, MATRIX_REG_DIGIT0 + digit, buffer[digit]); } + break; case MATRIX_ANIMATING: // update the cycle matrix->cycle++; @@ -76,6 +87,7 @@ void matrix_update(matrix_t *matrix, buffered_transceiver_t *transceiver) { if (matrix->state_cycle == DIGITS) { matrix->state = MATRIX_STABLE; + matrix_swap(matrix); } for (uint8_t digit = 0; digit < DIGITS - matrix->state_cycle; digit++) { @@ -85,5 +97,6 @@ void matrix_update(matrix_t *matrix, buffered_transceiver_t *transceiver) { for (uint8_t digit = DIGITS - matrix->state_cycle; digit < DIGITS; digit++) { matrix_send(matrix, MATRIX_REG_DIGIT0 + digit, other_buffer[digit - (DIGITS - matrix->state_cycle)]); } + break; } } diff --git a/arm07/src/timer.c b/arm07/src/timer.c index f551774..02a01c9 100644 --- a/arm07/src/timer.c +++ b/arm07/src/timer.c @@ -60,19 +60,37 @@ IRQn_Type timer_irq_idx(uint8_t line) { } } -void timer_enable_interrupt(timer_t *timer) { - timer_clear_interrupt(timer); - timer->periph->DIER |= TIM_DIER_UIE; +void timer_enable_interrupt(timer_t *timer, bool update, bool capture1) { + timer_clear_update_interrupt(timer); + timer_clear_capture1_interrupt(timer); + if (update) { + timer->periph->DIER |= TIM_DIER_UIE; + } + if (capture1) { + timer->periph->DIER |= TIM_DIER_CC1IE; + } IRQn_Type irq = timer_irq_idx(timer->idx); NVIC_SetPriority(irq, 1); NVIC_EnableIRQ(irq); } + void timer_disable_interrupt(timer_t *timer) { timer->periph->DIER &= ~TIM_DIER_UIE; + timer->periph->DIER &= ~TIM_DIER_CC1IE; } -uint32_t timer_is_interrupt(timer_t *timer) { + +uint32_t timer_is_update_interrupt(timer_t *timer) { return timer->periph->SR & TIM_SR_UIF; } -void timer_clear_interrupt(timer_t *timer) { + +uint32_t timer_is_capture1_interrupt(timer_t *timer) { + return timer->periph->SR & TIM_SR_CC1IF; +} + +void timer_clear_update_interrupt(timer_t *timer) { timer->periph->SR = ~TIM_SR_UIF; } + +void timer_clear_capture1_interrupt(timer_t *timer) { + timer->periph->SR = ~TIM_SR_CC1IF; +} diff --git a/arm07/src/uart.c b/arm07/src/uart.c index ba82226..0409434 100644 --- a/arm07/src/uart.c +++ b/arm07/src/uart.c @@ -46,9 +46,8 @@ void usart_configure_transmitter(uart_t* uart, bool enable) { uint16_t usart_transmit(uart_t *uart, char *data, uint16_t size) { for (int16_t i = 0; i < size; i++) { - char byte = *(data++); - while (!(uart->periph->SR & USART_SR_TXE)); + char byte = *(data++); uart->periph->DR = byte; } @@ -58,9 +57,26 @@ uint16_t usart_transmit(uart_t *uart, char *data, uint16_t size) { uint16_t usart_receive(uart_t* uart, char *buffer, uint16_t max_size) { uint16_t size = 0; - while (size < max_size - 1 && (uart->periph->SR & USART_SR_RXNE)) { + while (size < max_size && (uart->periph->SR & USART_SR_RXNE)) { *(buffer + (size++)) = (char)(uart->periph->DR & USART_DR_DR_Msk); } return size; } + +bool usart_can_transmit(uart_t* uart) { + return uart->periph->SR & USART_SR_TXE; +} +uint16_t usart_can_receive(uart_t* uart) { + return ((uart->periph->SR & USART_SR_RXNE) != 0) ? 1 : 0; +} + +void usart_enable_interrupt(uart_t *uart, bool tx, bool rx) { + reg_write_bits(&uart->periph->CR1, + (tx << USART_CR1_TXEIE_Pos) | (rx << USART_CR1_RXNEIE_Pos), + USART_CR1_TXEIE | USART_CR1_RXNEIE); + + // TODO: proper irq by idx + NVIC_SetPriority(USART2_IRQn, 1); + NVIC_EnableIRQ(USART2_IRQn); +} -- 2.48.1