None
None
combo LCD D4 pin
combo LCD D5 pin
combo LCD D6 pin
combo LCD D7 pin
combo LCD RS pin
combo LCD E pin
spinner Number of potential strings in print queue
int data;
int state; // 0..2 output high nybble, 3..5 output low, 6 ... delay for slow
// commands
int endstate; // final state, 6 for normal commands, 18 for slow
const char *initstr; // initialization string
__attribute__((noinline)) void print(const char *printstr) {
if (strings[wrindex])
return; // if queue full, drop string
strings[wrindex++] = printstr;
if (wrindex >= attr_qsize)
wrindex = 0;
}
const char *strings[attr_qsize]; // strings to output
int rdindex; // read index in circular string queue
int wrindex; // write index in circular string queue
palWritePad(attr_e, 0);
palSetPadMode(attr_d4, PAL_MODE_OUTPUT_PUSHPULL);
palSetPadMode(attr_d5, PAL_MODE_OUTPUT_PUSHPULL);
palSetPadMode(attr_d6, PAL_MODE_OUTPUT_PUSHPULL);
palSetPadMode(attr_d7, PAL_MODE_OUTPUT_PUSHPULL);
palSetPadMode(attr_rs, PAL_MODE_OUTPUT_PUSHPULL);
palSetPadMode(attr_e, PAL_MODE_OUTPUT_PUSHPULL);
state = 0;
// init: 0011, long wait - set 8 bit mode
// 0011, short wait - set 8 bit mode
// 0011, short wait - set 8 bit mode
// 0010, short wait - set 4 bit mode
// 0010 1000, short wait - 4 bit, function set:
// NFxx: N=1 => 2 lines, F=0 => 5x8 font
// 0000 1000, short wait - display off
// 0000 0001, long wait - display clear, set cursor and write addr home
// 0000 0110, short wait - entry mode set
// IS: I=1 => increment, S=0 => no shift
// 0000 1100, short wait - display on
// DCS: D=1 => display on, C=0 => no cursor, B=0 => no cursor blink
initstr = "\xf3\xb3\xb3\xb2\xb2\xb8\xb0\xb8\xb0\xf1\xb0\xb6\xb0\xbc"
"\x83"
"Axoloti on P6!";
strings[0] = initstr; // print initstring first
for (int i = 1; i < attr_qsize; i++) {
strings[i] = 0;
}
rdindex = 0; // start printing the init data
wrindex = 1; // next string to write
// LCD Data: when bit 7 is clear, output ASCII data with RS=1
// with bit 7 is set, set cursor position: bit 6 = line (0/1),
// bit 5..0 = column (0..47, 0..39 used normally)
// when bits 5,4 are 1,1 (i.e. column would have ben 48 and above)
// bits 3,2,1,0 are output in 4 bit mode, and bit 6 indicates delay
// (0=> normal (100µs), 1=>4.1ms
// states 0,1,2 are for high nybble (output data,rs, then e=0,1,0)
// states 3,4,5 are for low nybble (output data (rs unchanged), then e=0,1,0)
// state >=6 are for long delay, just bump state until reached endstate
switch (state) {
int rs;
case 0:
if (!strings[rdindex])
break; // nothing to print
data = *strings[rdindex]++;
if (data == 0) { // NUL
strings[rdindex++] = 0; // mark as read
if (rdindex >= attr_qsize)
rdindex = 0;
break; // start printing next time around
}
// we assume e is low here
endstate = 4; // default is fast timing
rs = 1; // default register is data register
if (data & 0x80) { // control when bit 7 set
// else output ASCII to display data RAM
rs = 0; // command register
if ((data & 0x30) ==
0x30) { // special 4-bit
// else display write position (no further conditioning needed)
if (data & 0x40)
endstate = 16; // long delay: 4 states + 12*0.33ms (i.e. 4ms)
data <<= 4; // 4-bit data is in low nybble
state = 2; // next state pulses e high, then low, then we're done (modulo
// potential delay)
}
}
palWritePad(attr_rs, rs);
palWritePad(attr_d4, (data >> 4) & 1); // high nybble first in LCD 4 bit mode
palWritePad(attr_d5, (data >> 5) & 1);
palWritePad(attr_d6, (data >> 6) & 1);
palWritePad(attr_d7, (data >> 7) & 1);
palWritePad(attr_e, 1);
state++;
break;
case 2:
palWritePad(attr_d4,
(data >> 0) & 1); // low nybble after first in LCD 4 bit mode
palWritePad(attr_d5, (data >> 1) & 1);
palWritePad(attr_d6, (data >> 2) & 1);
palWritePad(attr_d7, (data >> 3) & 1);
palWritePad(attr_e, 1);
state++;
break;
case 1:
case 3:
palWritePad(attr_e, 0);
// fall through
default:
state++;
if (state >= endstate)
state = 0; // restart cycle when endstate reached
break;
}