diff --git a/f103.pro b/f103-ledmatrix.pro similarity index 97% rename from f103.pro rename to f103-ledmatrix.pro index bdfeca4..00d38a8 100644 --- a/f103.pro +++ b/f103-ledmatrix.pro @@ -81,7 +81,8 @@ HEADERS += \ project/main.h \ project/utils/matcher.h \ project/utils/meanbuf.h \ - project/display.h + project/display.h \ + project/matrixdsp.h SOURCES += \ lib/cmsis/core_cm3.c \ @@ -138,7 +139,8 @@ SOURCES += \ project/utils/str_utils.c \ project/utils/matcher.c \ project/utils/meanbuf.c \ - project/display.c + project/display.c \ + project/matrixdsp.c DISTFILES += \ style.astylerc \ diff --git a/f103.pro.user b/f103.pro.user deleted file mode 100644 index 60c5465..0000000 --- a/f103.pro.user +++ /dev/null @@ -1,299 +0,0 @@ - - - - - - EnvironmentId - {dfe3cb4a-0f3e-4da9-9c52-5d2c464adafb} - - - ProjectExplorer.Project.ActiveTarget - 0 - - - ProjectExplorer.Project.EditorSettings - - true - false - true - - Cpp - - CppGlobal - - - - QmlJS - - QmlJSGlobal - - - 2 - UTF-8 - false - 4 - true - 80 - true - true - 1 - true - false - 0 - true - 0 - 8 - true - 1 - true - true - true - true - - - - ProjectExplorer.Project.PluginSettings - - - - 1 - - - - - ProjectExplorer.Project.Target.0 - - STLINK - STLINK - {15262c8f-05de-48ee-9452-3d289b21ba3e} - 0 - -1 - 0 - - /home/ondra/devel/f103 - - - true - Make - - Qt4ProjectManager.MakeStep - - -w - -r - - false - -B -j 4 - - - 1 - Build - - ProjectExplorer.BuildSteps.Build - - - - true - Make - - Qt4ProjectManager.MakeStep - - -w - -r - - true - clean - - - 1 - Clean - - ProjectExplorer.BuildSteps.Clean - - 2 - false - - Debug - Main - Qt4ProjectManager.Qt4BuildConfiguration - 2 - true - - 1 - 0 - - - false - 1000 - - true - - false - false - false - false - true - 0.01 - 10 - true - 1 - 25 - - 1 - true - false - true - valgrind - - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - 14 - - 2 - - flash - /usr/bin/make - %{buildDir} - Run /usr/bin/make - make flash - ProjectExplorer.CustomExecutableRunConfiguration - 3768 - false - true - false - false - true - - - false - 1000 - - true - - false - false - false - false - true - 0.01 - 10 - true - 1 - 25 - - 1 - true - false - true - valgrind - - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - 14 - - - f103 (via GDB server or hardware debugger) - - BareMetal/home/ondra/devel/f103/f103.pro - - f103.pro - 3768 - false - true - false - false - true - - - false - 1000 - - true - - false - false - false - false - true - 0.01 - 10 - true - 1 - 25 - - 1 - true - false - true - valgrind - - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10 - 11 - 12 - 13 - 14 - - 2 - - - /home/ondra/devel/f103/main.elf - /home/ondra/devel/f103 - Run /home/ondra/devel/f103/main.elf - - ProjectExplorer.CustomExecutableRunConfiguration - 3768 - false - true - false - false - true - - 3 - - - - ProjectExplorer.Project.TargetCount - 1 - - - ProjectExplorer.Project.Updater.FileVersion - 18 - - - Version - 18 - - diff --git a/project/hw_init.c b/project/hw_init.c index 2e9b194..5a470a5 100644 --- a/project/hw_init.c +++ b/project/hw_init.c @@ -8,11 +8,13 @@ #include "utils/timebase.h" #include "bus/event_queue.h" +#include "com/debug.h" // ---- Private prototypes -------- static void conf_gpio(void); static void conf_usart(void); +static void conf_spi(void); static void conf_systick(void); static void conf_subsystems(void); static void conf_irq_prios(void); @@ -27,6 +29,7 @@ void hw_init(void) conf_gpio(); conf_usart(); conf_systick(); + conf_spi(); conf_irq_prios(); conf_subsystems(); } @@ -71,6 +74,7 @@ static void conf_subsystems(void) static void conf_gpio(void) { GPIO_InitTypeDef gpio_cnf; + GPIO_StructInit(&gpio_cnf); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); @@ -96,6 +100,18 @@ static void conf_gpio(void) // A0-sonar trig | UART2 - debug, UART1 - esp gpio_cnf.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_9 | GPIO_Pin_10; gpio_cnf.GPIO_Mode = GPIO_Mode_AF_PP; + gpio_cnf.GPIO_Speed = GPIO_Speed_10MHz; + GPIO_Init(GPIOA, &gpio_cnf); + + // SPI + gpio_cnf.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7; + gpio_cnf.GPIO_Mode = GPIO_Mode_AF_PP; + gpio_cnf.GPIO_Speed = GPIO_Speed_10MHz; + GPIO_Init(GPIOA, &gpio_cnf); + // SPI NSS out + gpio_cnf.GPIO_Pin = GPIO_Pin_4; + gpio_cnf.GPIO_Mode = GPIO_Mode_Out_PP; + gpio_cnf.GPIO_Speed = GPIO_Speed_10MHz; GPIO_Init(GPIOA, &gpio_cnf); } @@ -115,6 +131,26 @@ static void conf_usart(void) data_iface = usart_iface_init(USART1, 460800, 256, 256); } +/** + * @brief Configure SPI + */ +static void conf_spi(void) +{ + RCC_APB2PeriphClockCmd(RCC_APB2ENR_SPI1EN, ENABLE); + + SPI_InitTypeDef spi_cnf; + SPI_StructInit(&spi_cnf); + + spi_cnf.SPI_Direction = SPI_Direction_1Line_Tx; + spi_cnf.SPI_Mode = SPI_Mode_Master; + spi_cnf.SPI_NSS = SPI_NSS_Soft; + spi_cnf.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8; + + SPI_Init(SPI1, &spi_cnf); + + SPI_Cmd(SPI1, ENABLE); +} + /** * @brief Configure 1 kHz SysTick w/ interrupt diff --git a/project/main.c b/project/main.c index d2a0395..7dd8b8d 100644 --- a/project/main.c +++ b/project/main.c @@ -13,7 +13,10 @@ #include #include -void poll_subsystems(void) +#include "matrixdsp.h" + + +static void poll_subsystems(void) { // poll serial buffers (runs callback) com_poll(debug_iface); @@ -36,29 +39,69 @@ void poll_subsystems(void) -void blinky(void* arg) -{ - (void)arg; - GPIOC->ODR ^= 1<<13; -} - - - - int main(void) { hw_init(); - display_init(); +// display_init(); - banner("*** STM32F103K8T6 RGB LED demo ***"); + banner("*** LED MATRIX DEMO ***"); banner_info("(c) Ondrej Hruska, 2016"); banner_info("Katedra mereni K338, CVUT FEL"); - - add_periodic_task(blinky, NULL, 500, false); + ms_time_t last; + + mdsp_send_command_all(CMD_DECODE_MODE, 0x00); + mdsp_send_command_all(CMD_SCAN_LIMIT, 0x07); + mdsp_send_command_all(CMD_SHUTDOWN, 0x01); + mdsp_send_command_all(CMD_DISPLAY_TEST, 0x00); + mdsp_send_command_all(CMD_INTENSITY, 0x05); + + mdsp_clear(); + + // --- + + const uint16_t inva0[] = { + 0b00100000100, + 0b00010001000, + 0b00111111100, + 0b01101110110, + 0b11111111111, + 0b10111111101, + 0b10100000101, + 0b00011011000, + }; + + const uint16_t inva1[] = { + 0b00100000100, + 0b10010001001, + 0b10111111101, + 0b11101110111, + 0b11111111111, + 0b01111111110, + 0b00100000100, + 0b01000000010, + }; while (1) { + if (ms_loop_elapsed(&last, 500)) { + GPIOC->ODR ^= 1 << 13; + } + poll_subsystems(); + + for (int i = 0; i < 8; i++) { + uint32_t x = __RBIT(inva0[7-i]); + mdsp_set(i, x >> 21); + mdsp_set(8+i, (x >> 29) & 0b111); + } + delay_ms(500); + + for (int i = 0; i < 8; i++) { + uint32_t x = __RBIT(inva1[7-i]); + mdsp_set(i, x >> 21); + mdsp_set(8+i, (x >> 29) & 0b111); + } + delay_ms(500); } } diff --git a/project/matrixdsp.c b/project/matrixdsp.c new file mode 100644 index 0000000..705e5a3 --- /dev/null +++ b/project/matrixdsp.c @@ -0,0 +1,87 @@ +#include +#include + +#include "com/debug.h" + +#include "utils/timebase.h" + +static void send_byte(uint8_t b) +{ + MDSP_SPIx->DR = b; + while (!(MDSP_SPIx->SR & SPI_SR_TXE)); +} + +static void set_nss(bool nss) +{ + if (nss) { + MDSP_NSS_GPIO->BSRR = MDSP_NSS_PIN; + } else { + MDSP_NSS_GPIO->BRR = MDSP_NSS_PIN; + } +} + +static void send_word(MDSP_Command cmd, uint8_t data) +{ + send_byte(cmd); + send_byte(data); +} + +/** + * @brief Send a command to n-th chained driver + * @param idx Driver index (0, 1, 2 ...) + * @param cmd command to send + * @param data command argument + */ +void mdsp_send_command(uint8_t idx, MDSP_Command cmd, uint8_t data) +{ + dbg("Set %d: cmd 0x%02x, data 0x%02x", idx, cmd, data); + + set_nss(false); + while (MDSP_SPIx->SR & SPI_SR_BSY); + + for (uint8_t i = 0; i < MDSP_CHAIN_COUNT - idx - 1; i++) { + send_word(CMD_NOOP, 0); + } + + send_word(cmd, data); + + for (uint8_t i = 0; i < idx; i++) { + send_word(CMD_NOOP, 0); + } + + while (MDSP_SPIx->SR & SPI_SR_BSY); + set_nss(false); + set_nss(true); +} + + +void mdsp_send_command_all(MDSP_Command cmd, uint8_t data) +{ + dbg("Set cmd 0x%02x, data 0x%02x ALL", cmd, data); + + set_nss(false); + while (MDSP_SPIx->SR & SPI_SR_BSY); + + for (uint8_t i = 0; i < MDSP_CHAIN_COUNT; i++) { + send_word(cmd, data); + } + + while (MDSP_SPIx->SR & SPI_SR_BSY); + + set_nss(false); + set_nss(true); +} + +void mdsp_set(uint8_t column, uint8_t bits) +{ + if (column >= MDSP_COLUMN_COUNT) return; + + mdsp_send_command(column >> 3, CMD_DIGIT0 + (column & 0x7), bits); +} + +void mdsp_clear(void) +{ + for (uint8_t i = 0; i < 8; i++) { + mdsp_send_command_all(CMD_DIGIT0+i, 0); + } +} diff --git a/project/matrixdsp.h b/project/matrixdsp.h new file mode 100644 index 0000000..f9cd124 --- /dev/null +++ b/project/matrixdsp.h @@ -0,0 +1,47 @@ +#ifndef MATRIXDSP_H +#define MATRIXDSP_H + +#include + +#define MDSP_SPIx SPI1 +#define MDSP_NSS_GPIO GPIOA +#define MDSP_NSS_PIN GPIO_Pin_4; + +#define MDSP_CHAIN_COUNT 4 +#define MDSP_COLUMN_COUNT (MDSP_CHAIN_COUNT*8) + +typedef enum { + CMD_NOOP = 0x00, + + CMD_DIGIT0 = 0x01, + CMD_DIGIT1 = 0x02, + CMD_DIGIT2 = 0x03, + CMD_DIGIT3 = 0x04, + CMD_DIGIT4 = 0x05, + CMD_DIGIT5 = 0x06, + CMD_DIGIT6 = 0x07, + CMD_DIGIT7 = 0x08, + + CMD_DECODE_MODE = 0x09, + CMD_INTENSITY = 0x0A, + CMD_SCAN_LIMIT = 0x0B, + CMD_SHUTDOWN = 0x0C, + CMD_DISPLAY_TEST = 0x0F, +} MDSP_Command; + +void mdsp_set(uint8_t column, uint8_t bits); + +void mdsp_clear(void); + +/** + * @brief Send a command to n-th chained driver + * @param idx Driver index (0, 1, 2 ...) + * @param cmd command to send + * @param data command argument + */ +void mdsp_send_command(uint8_t idx, MDSP_Command cmd, uint8_t data); + + +void mdsp_send_command_all(MDSP_Command cmd, uint8_t data); + +#endif // MATRIXDSP_H