parent
94662e35a8
commit
2b866d6623
@ -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); |
||||||
|
} |
@ -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
|
@ -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); |
|
||||||
} |
|
||||||
} |
|
@ -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
|
|
@ -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); |
||||||
|
} |
@ -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…
Reference in new issue