Added separate display firmware driver
This commit is contained in:
parent
e75eca4908
commit
2d03684b6d
2 changed files with 119 additions and 0 deletions
108
display/firmware/display.c
Normal file
108
display/firmware/display.c
Normal file
|
@ -0,0 +1,108 @@
|
|||
#include <avr/io.h>
|
||||
#include <util/delay.h>
|
||||
#include "display.h"
|
||||
|
||||
void display_init() {
|
||||
// PC5, PC6, PC7: output (VFD RS, RW, E), RS=0, RW=1, E=1
|
||||
// PD: output (VFD DB) - can be switched to input (pullup not needed)
|
||||
PORTC |= _BV(PC6) | _BV(PC7);
|
||||
DDRC |= _BV(PC5) | _BV(PC6) | _BV(PC7);
|
||||
PORTD = 0x00;
|
||||
DDRD = 0xff;
|
||||
}
|
||||
|
||||
uint8_t display_read_ir() {
|
||||
// switch PD to input
|
||||
DDRD = 0x00;
|
||||
// E=0 (enable/clock) RS=0 (IR) RW=1 (read)
|
||||
PORTC = (PORTC & ~(_BV(PC5) | _BV(PC7))) | _BV(PC6);
|
||||
_delay_us(0.23);
|
||||
// E=1 (enable/clock)
|
||||
PORTC |= _BV(PC7);
|
||||
_delay_us(0.16);
|
||||
uint8_t data = PIND;
|
||||
_delay_us(0.23 - 0.16);
|
||||
// E=0 (enable/clock)
|
||||
PORTC &= ~_BV(PC7);
|
||||
_delay_us(0.01);
|
||||
// reset to idle
|
||||
PORTC = _BV(PC6) | _BV(PC7);
|
||||
DDRD = 0xff;
|
||||
return data;
|
||||
}
|
||||
|
||||
uint8_t display_read_dr() {
|
||||
// switch PD to input
|
||||
DDRD = 0x00;
|
||||
// E=0 (enable/clock) RS=1 (IR) RW=1 (read)
|
||||
PORTC = (PORTC & ~_BV(PC7)) | (_BV(PC5) | _BV(PC6));
|
||||
_delay_us(0.23);
|
||||
// E=1 (enable/clock)
|
||||
PORTC |= _BV(PC7);
|
||||
_delay_us(0.16);
|
||||
uint8_t data = PIND;
|
||||
_delay_us(0.23 - 0.16);
|
||||
// E=0 (enable/clock)
|
||||
PORTC &= ~_BV(PC7);
|
||||
_delay_us(0.01);
|
||||
// reset to idle
|
||||
PORTC = _BV(PC6) | _BV(PC7);
|
||||
DDRD = 0xff;
|
||||
return data;
|
||||
}
|
||||
|
||||
void display_write_ir(uint8_t data) {
|
||||
// E=0 (enable/clock) RS=0 (IR) RW=0 (write)
|
||||
PORTC &= ~(_BV(PC5) | _BV(PC6) | _BV(PC7));
|
||||
_delay_us(0.23);
|
||||
// E=1 (enable/clock)
|
||||
PORTC |= _BV(PC7);
|
||||
// data
|
||||
PORTD = data;
|
||||
_delay_us(0.23);
|
||||
// E=0 (enable/clock)
|
||||
PORTC &= ~_BV(PC7);
|
||||
_delay_us(0.01);
|
||||
// reset to idle
|
||||
PORTC = _BV(PC6) | _BV(PC7);
|
||||
PORTD = 0x00;
|
||||
}
|
||||
|
||||
void display_write_dr(uint8_t data) {
|
||||
// E=0 (enable/clock) RS=1 (IR) RW=0 (write)
|
||||
PORTC = (PORTC & ~(_BV(PC6) | _BV(PC7))) | _BV(PC5);
|
||||
_delay_us(0.23);
|
||||
// E=1 (enable/clock)
|
||||
PORTC |= _BV(PC7);
|
||||
// data
|
||||
PORTD = data;
|
||||
_delay_us(0.23);
|
||||
// E=0 (enable/clock)
|
||||
PORTC &= ~_BV(PC7);
|
||||
_delay_us(0.01);
|
||||
// reset to idle
|
||||
PORTC = _BV(PC6) | _BV(PC7);
|
||||
PORTD = 0x00;
|
||||
}
|
||||
|
||||
|
||||
bool display_wait_ready() {
|
||||
// if the busy flag never goes high, we'll run into a deadlock here.
|
||||
// let's put a deadline on the wait loop.
|
||||
for (uint8_t i = 0; i < 100; i++) {
|
||||
// read_ir() takes about 500ns
|
||||
if (display_read_ir() & _BV(7)) return true;
|
||||
// wait 10us until the next status read
|
||||
_delay_us(10 - 0.5);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void display_write(uint8_t command, const uint8_t *data, uint8_t length) {
|
||||
if (display_wait_ready()) {
|
||||
display_write_ir(command);
|
||||
for (uint8_t i = 0; i < length; i++) {
|
||||
display_write_dr(data[i]);
|
||||
}
|
||||
}
|
||||
}
|
11
display/firmware/display.h
Normal file
11
display/firmware/display.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
void display_init();
|
||||
void display_write(uint8_t command, const uint8_t *data, uint8_t length);
|
||||
|
||||
uint8_t display_read_ir();
|
||||
uint8_t display_read_dr();
|
||||
void display_write_ir(uint8_t data);
|
||||
void display_write_dr(uint8_t data);
|
||||
bool display_wait_ready();
|
Loading…
Reference in a new issue