Skip to content

Instantly share code, notes, and snippets.

@four0four
Last active September 18, 2020 07:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save four0four/e9b38a3839706d2fb342c2975c0c6757 to your computer and use it in GitHub Desktop.
Save four0four/e9b38a3839706d2fb342c2975c0c6757 to your computer and use it in GitHub Desktop.
NA202MD08BC driver
#include <stdint.h>
#include <string.h>
#include <avr/io.h>
#include <avr/interrupt.h>
/*
* NA202MD08BC pinout:
* 1 2
* [-----|-----]
* [ vcc | vcc ]
* [ vcc | vcc ]
* [ ck0 | vcc ]
* [ vss | vss ]
* [ d_1 | vss ]
* [ #CL | vss ]
* [ d_0 | vss ]
* [ ck1 | vss ]
* [ vss | vss ]
* [ vcc | vcc ]
* 10 20
*
* ck0/d_0: 40-bit shift register connected to pixels
* ck1/d_1: 40-bit shift register connected to digits
* #CL: global blanking strobe
*
*
* apparently ck1 is attached to LS?!
* so we can -not- blank, and shift in during low clk
*/
#define DIGIT_PORT PORTB
#define DIGIT_PIN PINB
#define DIGIT_DDR DDRB
// idk same port as OC1A
#define DIGIT_DATA_BIT (1<<0)
// OC1A
#define DIGIT_CLOCK_BIT (1<<1)
#define BLANK_PORT PORTD
#define BLANK_DDR DDRD
#define BLANK_BIT (1<<2)
#define PX_PORT PORTB
#define PX_PIN PINB
#define PX_DDR DDRB
// SPI on PORTB
#define PX_DATA_BIT (1<<3)
#define PX_CLOCK_BIT (1<<5)
#define BAUD 9600
// 40 px per 40 digits
volatile uint8_t framebuf[40][5];
volatile uint8_t flags = 2;
// pixel pointer
volatile uint8_t px_idx = 0;
// digit pointer
volatile uint16_t digit_idx = 0;
// uart write pos
// these are 16 bit because I think
// there is a silicon bug which corrupts
// them if they're bytes. the flash
// buf is 16 bits so it's believable
// iow: "works in my emulator"
volatile uint16_t write_ptr = 0;
volatile uint16_t write_px = 0;
// fires twice per 200hz period
ISR(TIMER1_COMPA_vect) {
// just moved a digit forward, update pixels:
if(flags & 1) {
flags |= 2;
px_idx=0;
}
else {
digit_idx+=1;
// do we need to clock in our scanning bit?
if (digit_idx == 40) {
DIGIT_PORT |= DIGIT_DATA_BIT;
digit_idx = 0;
}
else DIGIT_PORT &= ~DIGIT_DATA_BIT;
}
flags = flags ^ 1;
}
// there is some timing slack here
// so just defer to the main loop
ISR(SPI_STC_vect) {
flags |= 4;
}
// lol whatever
ISR(USART_RX_vect) {
char t = UDR0;
/*
if(t == 0x41) {
write_px = 0;
write_ptr = 0;
framebuf[0][0]=0x00;
framebuf[0][1]=0xff;
framebuf[0][2]=0;
framebuf[0][3]=0;
framebuf[0][4]=0;
framebuf[1][0]=0x1f;
framebuf[1][1]=0x00;
framebuf[1][2]=0xff;
framebuf[1][3]=0xff;
framebuf[1][4]=0xff;
}
else if (t == 0x42) {
write_px = 0;
write_ptr = 0;
framebuf[1][0]=0x00;
framebuf[1][1]=0xff;
framebuf[1][2]=0;
framebuf[1][3]=0;
framebuf[1][4]=0;
framebuf[0][0]=0x1f;
framebuf[0][1]=0x00;
framebuf[0][2]=0xff;
framebuf[0][3]=0xff;
framebuf[0][4]=0xff;
}
*/
if (t == 0x1b) {
write_ptr = write_px = 0;
}
else {
framebuf[write_ptr][write_px] = t;
++write_px;
if(write_px >= 5){
write_px = 0;
if(++write_ptr >= 40) write_ptr = 0;
}
}
}
void init_periph() {
cli();
SPCR = 0x50;
SPSR = 0x00;
// ugly io shit
DIGIT_DDR |= (DIGIT_CLOCK_BIT | DIGIT_DATA_BIT);
DIGIT_PORT &= ~(DIGIT_CLOCK_BIT);
DIGIT_PORT |= DIGIT_DATA_BIT;
PX_DDR |= (PX_CLOCK_BIT | PX_DATA_BIT);
PX_PORT &= ~(PX_CLOCK_BIT | PX_DATA_BIT);
// fuck #SS
DDRB |= (1<<2);
PORTB |= (1<<2);
// timer1:
// toggle OC1A on compare
// prescalar 8
// match 125 for 200hz update
const uint16_t digit_count = 75;
TCCR1A = 0x40;
TCCR1B = 0x0a;
OCR1AH = digit_count >> 8;
OCR1AL = digit_count & 0xff;
TIMSK1 = 0x02;
// uart, rx/tx, rx irq, 115200 baud
UCSR0A = 0x00;
UCSR0B = 0x98;
UCSR0C = 0x06;
const uint16_t ubrr = F_CPU/16/BAUD-1;
UBRR0H = ubrr>>8;
UBRR0L = ubrr&0xff;
memset((void*)framebuf, 0, 200);
// fucking around:
framebuf[0][0]=0xFF;
framebuf[0][1]=0x00;
framebuf[0][2]=0xff;
framebuf[0][3]=0xff;
framebuf[0][4]=0xff;
framebuf[2][4]=0xff;
framebuf[3][3]=0xff;
framebuf[39][4] = 0x00;
// framebuf[39][3] = 0xff;
write_px = 0;
write_ptr = 0;
// interrupts and shit on
sei();
}
int main() {
init_periph();
while(1) {
if (flags & 2) {
flags = flags & ~2;
// enable spi interrupt and kick out initial byte
cli();
SPCR |= (1<<SPIE);
SPDR = framebuf[digit_idx][0];
sei();
}
if(flags&4) {
cli();
flags &= ~4;
px_idx += 1;
SPDR = framebuf[digit_idx][px_idx];
sei();
// completed writing a digit:
// release #blank and turn off the irq
if (px_idx == 4){
SPCR &= ~(1<<SPIE);
//BLANK_PORT |= BLANK_BIT;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment