From 762518416b9b430ce46e7262558827d1e1a9b665 Mon Sep 17 00:00:00 2001 From: sergeyyarkov Date: Fri, 14 Aug 2026 19:26:32 +0300 Subject: [PATCH] avr --- README.md | 27 ++++++++++++++ config_avr.h | 47 ++++++++++++++++++++++++ pdsp188x.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++ pdsp188x.h | 57 +++++++++++++++++++++++++++++ port/avr/avr.c | 41 +++++++++++++++++++++ port/avr/avr.h | 9 +++++ 6 files changed, 278 insertions(+) create mode 100644 README.md create mode 100644 config_avr.h create mode 100644 pdsp188x.c create mode 100644 pdsp188x.h create mode 100644 port/avr/avr.c create mode 100644 port/avr/avr.h diff --git a/README.md b/README.md new file mode 100644 index 0000000..ef5d825 --- /dev/null +++ b/README.md @@ -0,0 +1,27 @@ +# PDSP188x Dot Matrix Display Interfacing Library + +This library provides an interfacing API for displaying characters and numbers. + +## Example Usage + +1. Clone the repository and configure the port numbers inside the `config_{arch}.h` file. +2. Pass the interface implementation into the initialization function: + +```c +#include "main.h" +#include "pdsp188x/port/avr/avr.h" + +int main(void) { + uint16_t counter = 0; + + PDSP188x_Init(&PDSP188x_AVR_Driver); + PDSP188x_SetBrightness(PDSP188x_BRIGHTNESS_LEVEL_100); + + while (1) { + PDSP188x_Clear(); + PDSP188x_SendStr("C="); + PDSP188x_SendInt16(counter++); + _delay_ms(500); + } +} +``` diff --git a/config_avr.h b/config_avr.h new file mode 100644 index 0000000..c3a004c --- /dev/null +++ b/config_avr.h @@ -0,0 +1,47 @@ +#if !defined(PDSP188x_CONFIG_AVR_H_) +# define PDSP188x_CONFIG_AVR_H_ + +# include +# include + +# define DATA_PORT PORTB +# define DATA_DIR DDRB + +/** + * Control using 595 shift register + */ +# define LATCH _BV(PB4) +# define DATA _BV(PB5) +# define CLK _BV(PB7) + +/** + * Writes data into display when WR=0. Note CE=0 to enable write cycle. + */ +# define WR _BV(PB0) + +/** + * Accesses Flash RAM. Address inputs A0–A2 select digit address + * while data bit D0 sets (D0=1) or resets (D0=0) Flash bit, A3 and A4 ignored + */ +# define FL _BV(PB1) + +/** + * Initializes display; clears Character RAM (20H), Flash RAM (00H), control word (00H), and resets + * internal counters. UDC Address Register and UDC RAM unaffected. + */ +# define RST _BV(PB6) + +# define ADDR_PORT PORTC +# define ADDR_DIR DDRC + +/** + * A0–A2 select specific digits + * A3 and A4 access parts of memory together with Flash pin + */ +# define A0 _BV(PC3) +# define A1 _BV(PC4) +# define A2 _BV(PC5) +# define A3 _BV(PC6) +# define A4 _BV(PC7) + +#endif \ No newline at end of file diff --git a/pdsp188x.c b/pdsp188x.c new file mode 100644 index 0000000..fcc2a34 --- /dev/null +++ b/pdsp188x.c @@ -0,0 +1,97 @@ +#include "pdsp188x.h" + +static const PDSP188x_DriverInterface_t *driver = {NULL}; + +static void SetDataLine(uint8_t pin_mask) { driver->set_pins(PDSP188x_DATA_LINE_MASK, pin_mask, 1); } +static void ClearDataLine(uint8_t pin_mask) { driver->set_pins(PDSP188x_DATA_LINE_MASK, pin_mask, 0); } +static void SetAddrLine(uint8_t pin_mask) { driver->set_pins(PDSP188x_ADDR_LINE_MASK, pin_mask, 1); } +static void ClearAddrLine(uint8_t pin_mask) { driver->set_pins(PDSP188x_ADDR_LINE_MASK, pin_mask, 0); } + +#define MemSelectCharRAM() SetAddrLine(A3 | A4) +#define MemSelectControlWord() SetAddrLine(A4) +#define MemSelectNone() ClearAddrLine(A3 | A4) +#define SetAddrNone() ClearAddrLine(A0 | A1 | A2 | A3 | A4) +#define FlashCycle() \ + do { \ + ClearDataLine(WR); \ + _delay_us(1); \ + SetDataLine(WR); \ + _delay_us(1); \ + } while (0) + +uint8_t pos = 0; + +void PDSP188x_Init(const PDSP188x_DriverInterface_t *driver_strategy) { + if (driver_strategy != NULL) { + driver = driver_strategy; + if (driver->init != NULL) { + driver->init(); + } + } +} + +void PDSP188x_SetBrightness(uint8_t level) { + if (driver == NULL || driver->send_byte == NULL) return; + + MemSelectNone(); + SetAddrLine(A4); + driver->send_byte(level); + FlashCycle(); + _delay_us(5); +} + +void PDSP188x_SendChar(char c, uint8_t digit) { + if (driver == NULL || driver->send_byte == NULL) return; + + driver->send_byte(c); + _delay_us(1); + MemSelectCharRAM(); + + /* digit set */ + if (digit & 0x01) SetAddrLine(A0); + if (digit & 0x02) SetAddrLine(A1); + if (digit & 0x04) SetAddrLine(A2); + + _delay_us(1); + FlashCycle(); + SetAddrNone(); + _delay_us(1); +} + +void PDSP188x_Clear(void) { + for (uint8_t i = 0; i <= 7; i++) { + PDSP188x_SendChar(0x20, i); + } + + pos = 0; +} + +void PDSP188x_SendStr(char *str) { + char c; + + while ((c = *str) != '\0') { + if (pos > 7) { + pos = 0; + return; + } + PDSP188x_SendChar(*str++, pos++); + } +} +void PDSP188x_BlinkEn(uint8_t control) { + uint8_t control_command = control ? 0x10 : 0; + + SetAddrNone(); + MemSelectControlWord(); + SetDataLine(FL); + + driver->send_byte(control_command); + + FlashCycle(); +} + +void PDSP188x_SendInt16(int16_t n) { + char str[12] = {'\0'}; + + itoa(n, str, 10); + PDSP188x_SendStr(str); +} \ No newline at end of file diff --git a/pdsp188x.h b/pdsp188x.h new file mode 100644 index 0000000..c1d4c29 --- /dev/null +++ b/pdsp188x.h @@ -0,0 +1,57 @@ +#if !defined(_PDSP188x_H_) +# define _PDSP188x_H_ + +# include +# include +# include + +# ifdef __AVR__ + +# include "config_avr.h" + +# else + +# define WR (1 << 0) +# define FL (1 << 1) +# define LATCH (1 << 2) +# define RST (1 << 3) +# define DATA (1 << 4) +# define CLK (1 << 5) + +# define A0 (1 << 0) +# define A1 (1 << 1) +# define A2 (1 << 2) +# define A3 (1 << 3) +# define A4 (1 << 4) + +# endif + +# define PDSP188x_DATA_LINE_MASK 0x01 +# define PDSP188x_ADDR_LINE_MASK 0x02 + +typedef struct { + void (*init)(void); + void (*reset)(void); + void (*send_byte)(uint8_t byte); + void (*write_char)(char c, uint8_t pos); + void (*set_pins)(uint8_t set_mask, uint8_t pin, uint8_t state); +} PDSP188x_DriverInterface_t; + +# define PDSP188x_BRIGHTNESS_LEVEL_100 0x00 +# define PDSP188x_BRIGHTNESS_LEVEL_80 0x01 +# define PDSP188x_BRIGHTNESS_LEVEL_53 0x02 +# define PDSP188x_BRIGHTNESS_LEVEL_40 0x03 +# define PDSP188x_BRIGHTNESS_LEVEL_27 0x04 +# define PDSP188x_BRIGHTNESS_LEVEL_20 0x05 +# define PDSP188x_BRIGHTNESS_LEVEL_13 0x06 +# define PDSP188x_BRIGHTNESS_LEVEL_0 0x07 + +void PDSP188x_Init(const PDSP188x_DriverInterface_t *driver); +void PDSP188x_SendChar(char c, uint8_t digit); +void PDSP188x_SendStr(char *str); +void PDSP188x_SendInt16(int16_t n); +void PDSP188x_SetBrightness(uint8_t level); +void PDSP188x_BlinkEn(uint8_t control); +void PDSP188x_Clear(void); + +#endif \ No newline at end of file diff --git a/port/avr/avr.c b/port/avr/avr.c new file mode 100644 index 0000000..9b882bf --- /dev/null +++ b/port/avr/avr.c @@ -0,0 +1,41 @@ +#include "avr.h" + +#include "../../config_avr.h" + +static void SetPins(uint8_t mask, uint8_t pin_mask, uint8_t state) { + if (state && mask == PDSP188x_DATA_LINE_MASK) DATA_PORT |= pin_mask; + if (state && mask == PDSP188x_ADDR_LINE_MASK) ADDR_PORT |= pin_mask; + if (!state && mask == PDSP188x_DATA_LINE_MASK) DATA_PORT &= ~pin_mask; + if (!state && mask == PDSP188x_ADDR_LINE_MASK) ADDR_PORT &= ~pin_mask; +} + +static void Init(void) { + DATA_DIR |= WR | FL | CLK | DATA | LATCH | RST; + ADDR_DIR |= A0 | A1 | A2 | A3 | A4; + DATA_PORT |= FL | RST; + SPCR |= _BV(SPE) | _BV(MSTR) | _BV(SPR1) | _BV(SPR0); + + _delay_ms(10); + + /* reset */ + DATA_PORT |= _BV(WR) | _BV(FL); + DATA_PORT &= ~_BV(RST); + _delay_us(1); + DATA_PORT |= _BV(RST); + + _delay_ms(1); + + DATA_PORT |= WR; +} + +static void SendByte(uint8_t byte) { + SPDR = byte; + loop_until_bit_is_set(SPSR, SPIF); + _delay_us(5); + DATA_PORT |= LATCH; + _delay_us(5); + DATA_PORT &= ~LATCH; + _delay_us(5); +} + +const PDSP188x_DriverInterface_t PDSP188x_AVR_Driver = {.init = Init, .send_byte = SendByte, .set_pins = SetPins}; \ No newline at end of file diff --git a/port/avr/avr.h b/port/avr/avr.h new file mode 100644 index 0000000..366d708 --- /dev/null +++ b/port/avr/avr.h @@ -0,0 +1,9 @@ +#ifndef PDSP188x_AVR_H_ +#define PDSP188x_AVR_H_ + +#include "../../pdsp188x.h" +#include "util/delay.h" + +extern const PDSP188x_DriverInterface_t PDSP188x_AVR_Driver; + +#endif \ No newline at end of file