Browse Source

implemented backing array & low lvl funcs

memlib
Ondřej Hruška 6 years ago
parent
commit
2b866d6623
  1. 6
      f103-ledmatrix.pro
  2. 48
      project/dotmatrix.c
  3. 37
      project/dotmatrix.h
  4. 115
      project/main.c
  5. 2
      project/malloc_safe.c
  6. 86
      project/matrixdsp.c
  7. 47
      project/matrixdsp.h
  8. 73
      project/max2719.c
  9. 61
      project/max2719.h

6
f103-ledmatrix.pro

@ -82,7 +82,8 @@ HEADERS += \
project/utils/matcher.h \
project/utils/meanbuf.h \
project/display.h \
project/matrixdsp.h
project/max2719.h \
project/dotmatrix.h
SOURCES += \
lib/cmsis/core_cm3.c \
@ -140,7 +141,8 @@ SOURCES += \
project/utils/matcher.c \
project/utils/meanbuf.c \
project/display.c \
project/matrixdsp.c
project/max2719.c \
project/dotmatrix.c
DISTFILES += \
style.astylerc \

48
project/dotmatrix.c

@ -0,0 +1,48 @@
#include "max2719.h"
#include "dotmatrix.h"
#include "malloc_safe.h"
DotMatrix_Cfg* dmtx_init(DotMatrix_Init *init)
{
DotMatrix_Cfg *dmtx = calloc_s(1, sizeof(DotMatrix_Cfg));
dmtx->drv.SPIx = init->SPIx;
dmtx->drv.CS_GPIOx = init->CS_GPIOx;
dmtx->drv.CS_PINx = init->CS_PINx;
dmtx->drv.chain_len = init->cols * init->rows;
dmtx->cols = init->cols;
dmtx->rows = init->rows;
dmtx->screen = calloc_s(init->cols * init->rows * 8, 1); // 8 bytes per driver
max2719_cmd_all(&dmtx->drv, MAX2719_CMD_DECODE_MODE, 0x00); // no decode
max2719_cmd_all(&dmtx->drv, MAX2719_CMD_SCAN_LIMIT, 0x07); // scan all 8
max2719_cmd_all(&dmtx->drv, MAX2719_CMD_SHUTDOWN, 0x01); // not shutdown
max2719_cmd_all(&dmtx->drv, MAX2719_CMD_DISPLAY_TEST, 0x00); // not test
max2719_cmd_all(&dmtx->drv, MAX2719_CMD_INTENSITY, 0x07); // half intensity
// clear
for (uint8_t i = 0; i < 8; i++) {
max2719_cmd_all(&dmtx->drv, MAX2719_CMD_DIGIT0+i, 0);
}
return dmtx;
}
void dmtx_show(DotMatrix_Cfg* dmtx)
{
for (uint8_t i = 0; i < 8; i++) {
// show each digit's array in turn
max2719_cmd_all_data(&dmtx->drv, MAX2719_CMD_DIGIT0+i, dmtx->screen + (i * dmtx->drv.chain_len));
}
}
void dmtx_intensity(DotMatrix_Cfg* dmtx, uint8_t intensity)
{
max2719_cmd_all(&dmtx->drv, MAX2719_CMD_INTENSITY, intensity & 0x0F);
}
void dmtx_blank(DotMatrix_Cfg* dmtx, bool blank)
{
max2719_cmd_all(&dmtx->drv, MAX2719_CMD_SHUTDOWN, blank & 0x01);
}

37
project/dotmatrix.h

@ -0,0 +1,37 @@
#ifndef MATRIXDSP_H
#define MATRIXDSP_H
#include "main.h"
#include "max2719.h"
typedef struct {
MAX2719_Cfg drv;
uint8_t *screen; /*!< Screen array, organized as series of [all #1 digits], [all #2 digits] ... */
uint32_t cols; /*!< Number of drivers horizontally */
uint32_t rows; /*!< Number of drivers vertically */
} DotMatrix_Cfg;
typedef struct {
SPI_TypeDef *SPIx; /*!< SPI iface used by this instance */
GPIO_TypeDef *CS_GPIOx; /*!< Chip select GPIO port */
uint16_t CS_PINx; /*!< Chip select pin mask */
uint32_t cols; /*!< Number of drivers horizontally */
uint32_t rows; /*!< Number of drivers vertically */
} DotMatrix_Init;
DotMatrix_Cfg* dmtx_init(DotMatrix_Init *init);
/**
* @brief Display the whole screen array
* @param dmtx : driver struct
*/
void dmtx_show(DotMatrix_Cfg* dmtx);
/** Set intensity 0-16 */
void dmtx_intensity(DotMatrix_Cfg* dmtx, uint8_t intensity);
/** Display on/off */
void dmtx_blank(DotMatrix_Cfg* dmtx, bool blank);
#endif // MATRIXDSP_H

115
project/main.c

@ -13,104 +13,71 @@
#include <math.h>
#include <sbmp.h>
#include "matrixdsp.h"
//#include "matrixdsp.h"
#include "max2719.h"
#include "dotmatrix.h"
static void poll_subsystems(void)
{
// poll serial buffers (runs callback)
com_poll(debug_iface);
com_poll(data_iface);
// run queued tasks
tq_poll();
// handle queued events
Event evt;
until_timeout(2) { // take 2 ms max
if (eq_take(&evt)) {
run_event_handler(&evt);
} else {
break;
}
}
}
static void poll_subsystems(void);
static DotMatrix_Cfg *dmtx;
int main(void)
{
hw_init();
// display_init();
banner("*** LED MATRIX DEMO ***");
banner_info("(c) Ondrej Hruska, 2016");
banner_info("Katedra mereni K338, CVUT FEL");
ms_time_t last;
DotMatrix_Init dmtx_cfg;
dmtx_cfg.CS_GPIOx = GPIOA;
dmtx_cfg.CS_PINx = GPIO_Pin_4;
dmtx_cfg.SPIx = SPI1;
dmtx_cfg.cols = 4;
dmtx_cfg.rows = 1;
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, 0x0F);
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,
};
dmtx = dmtx_init(&dmtx_cfg);
dmtx->screen[0] = 0xF0;
dmtx->screen[4] = 0x0F;
dmtx_show(dmtx);
ms_time_t last;
while (1) {
if (ms_loop_elapsed(&last, 500)) {
GPIOC->ODR ^= 1 << 13;
}
poll_subsystems();
for(int i = 0; i < 8; i++) {
mdsp_send_command_all(CMD_DIGIT0+i, i);
}
delay_ms(500);
dmtx_blank(dmtx, false);
delay_ms(250);
dmtx_blank(dmtx, true);
delay_ms(250);
}
}
for(int i = 7; i >= 0; i--) {
mdsp_send_command_all(CMD_DIGIT0+i, 0x00);
}
delay_ms(500);
/*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);
static void poll_subsystems(void)
{
// poll serial buffers (runs callback)
com_poll(debug_iface);
com_poll(data_iface);
// run queued tasks
tq_poll();
// handle queued events
Event evt;
until_timeout(2) { // take 2 ms max
if (eq_take(&evt)) {
run_event_handler(&evt);
} else {
break;
}
delay_ms(500);*/
}
}

2
project/malloc_safe.c

@ -29,7 +29,7 @@ void *malloc_safe_do(size_t size, const char* file, uint32_t line)
void *calloc_safe_do(size_t nmemb, size_t size, const char* file, uint32_t line)
{
void *mem = calloc(size, nmemb);
void *mem = calloc(nmemb, size);
if (mem == NULL) {
// malloc failed
error("Malloc failed in file %s on line %"PRIu32, file, line);

86
project/matrixdsp.c

@ -1,86 +0,0 @@
#include <main.h>
#include <matrixdsp.h>
#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);
}
}

47
project/matrixdsp.h

@ -1,47 +0,0 @@
#ifndef MATRIXDSP_H
#define MATRIXDSP_H
#include <main.h>
#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

73
project/max2719.c

@ -0,0 +1,73 @@
#include "max2719.h"
static inline
void send_byte(MAX2719_Cfg *inst, uint8_t b)
{
inst->SPIx->DR = b;
while (!(inst->SPIx->SR & SPI_SR_TXE));
}
static inline
void set_nss(MAX2719_Cfg *inst, bool nss)
{
if (nss) {
inst->CS_GPIOx->BSRR = inst->CS_PINx;
} else {
inst->CS_GPIOx->BRR = inst->CS_PINx;
}
}
static void send_word(MAX2719_Cfg *inst, MAX2719_Command cmd, uint8_t data)
{
send_byte(inst, cmd);
send_byte(inst, data);
}
void max2719_cmd(MAX2719_Cfg *inst, uint32_t nth, MAX2719_Command cmd, uint8_t data)
{
set_nss(inst, 0);
while (inst->SPIx->SR & SPI_SR_BSY);
for (uint32_t i = 0; i < inst->chain_len; i++) {
if (i == inst->chain_len - nth - 1) {
send_word(inst, cmd, data);
} else {
send_word(inst, MAX2719_CMD_NOOP, 0);
}
}
while (inst->SPIx->SR & SPI_SR_BSY);
set_nss(inst, 1);
}
void max2719_cmd_all(MAX2719_Cfg *inst, MAX2719_Command cmd, uint8_t data)
{
set_nss(inst, 0);
while (inst->SPIx->SR & SPI_SR_BSY);
for (uint32_t i = 0; i < inst->chain_len; i++) {
send_word(inst, cmd, data);
}
while (inst->SPIx->SR & SPI_SR_BSY);
set_nss(inst, 1);
}
void max2719_cmd_all_data(MAX2719_Cfg *inst, MAX2719_Command cmd, uint8_t *data)
{
set_nss(inst, 0);
while (inst->SPIx->SR & SPI_SR_BSY);
for (uint32_t i = 0; i < inst->chain_len; i++) {
send_word(inst, cmd, data[inst->chain_len - i - 1]);
}
while (inst->SPIx->SR & SPI_SR_BSY);
set_nss(inst, 1);
}

61
project/max2719.h

@ -0,0 +1,61 @@
#ifndef MAX2719_H
#define MAX2719_H
#include <main.h>
/** Generic utilities for controlling the MAX2719 display driver */
typedef struct {
SPI_TypeDef *SPIx; /*!< SPI iface used by this instance */
GPIO_TypeDef *CS_GPIOx; /*!< Chip select GPIO port */
uint16_t CS_PINx; /*!< Chip select pin mask */
uint32_t chain_len; /*!< Number of daisy-chained drivers (for "all" or "n-th" commands */
} MAX2719_Cfg;
typedef enum {
MAX2719_CMD_NOOP = 0x00,
MAX2719_CMD_DIGIT0 = 0x01,
MAX2719_CMD_DIGIT1 = 0x02,
MAX2719_CMD_DIGIT2 = 0x03,
MAX2719_CMD_DIGIT3 = 0x04,
MAX2719_CMD_DIGIT4 = 0x05,
MAX2719_CMD_DIGIT5 = 0x06,
MAX2719_CMD_DIGIT6 = 0x07,
MAX2719_CMD_DIGIT7 = 0x08,
MAX2719_CMD_DECODE_MODE = 0x09,
MAX2719_CMD_INTENSITY = 0x0A,
MAX2719_CMD_SCAN_LIMIT = 0x0B,
MAX2719_CMD_SHUTDOWN = 0x0C,
MAX2719_CMD_DISPLAY_TEST = 0x0F,
} MAX2719_Command;
/**
* @brief Send a command to a single driver
* @param inst : config struct
* @param nth : driver index
* @param cmd : command
* @param data : data byte
*/
void max2719_cmd(MAX2719_Cfg *inst, uint32_t nth, MAX2719_Command cmd, uint8_t data);
/**
* @brief Send command to all drivers, with the same data
* @param inst : config struct
* @param cmd : command
* @param data : data byte
*/
void max2719_cmd_all(MAX2719_Cfg *inst, MAX2719_Command cmd, uint8_t data);
/**
* @brief Send command to all drivers, with varying data
* @param inst : config struct
* @param cmd : command
* @param data : array of data bytes (must be long to cover all drivers)
*/
void max2719_cmd_all_data(MAX2719_Cfg *inst, MAX2719_Command cmd, uint8_t *data);
#endif // MAX2719_H
Loading…
Cancel
Save