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