implement I²C modes/calls

This commit is contained in:
King Kévin 2022-06-22 18:15:02 +02:00
parent d3b5533f57
commit 1e446cbb0b
1 changed files with 67 additions and 14 deletions

81
main.c
View File

@ -52,10 +52,26 @@
// the I²C address of this slave
#define I2C_ADDR 0x28
// the functions we can call over I²C
enum i2c_mode_t {
MODE_INSTRUCTION, // read/write instruction/command
MODE_DATA, // read/write data
MODE_PORT, // read/write
// custom modes
MODE_CLEAR_DISPLAY, // clear display
MODE_LINE1, // write to line 1
MODE_LINE2, // write to line 2
MODE_DISPLAY_ON, // turn display on
MODE_DISPLAY_OFF, // turn display off
MODE_BRIGHTNESS, // set backlight brightness
// raw instructions, directly mapping to HD44780
MODE_DISPLAY,
MODE_RETURN_HOME,
MODE_ENTRY_MODE_SET,
MODE_CURSOR_DISPLAY_SHIFT,
MODE_FUNCTION_SET,
MODE_CGRAM_ADDR,
MODE_DDRAM_ADDR,
MODE_DATA,
MODE_COUNT, // number of modes
};
@ -269,7 +285,7 @@ void main(void)
wait_10us(4 + 1); // wait 37 us (BF could be checked at this point)
// we are now for sure in 8-bit more (and could switch do 4-bit). 8-bit mode is actually the default after power up
IWDG_KR = IWDG_KR_KEY_REFRESH; // reset watchdog
hd44780_write_instruction(0x20); // function set: 4-bit mode
hd44780_write_instruction(0x28); // function set (DL=1: 4-bit mode, N=1: 2 lines, F=0: 5x8 dots)
hd44780_write_instruction(0x08); // display off
hd44780_write_instruction(0x01); // display clear
hd44780_write_instruction(0x06); // entry mode set
@ -289,26 +305,63 @@ void main(void)
if (i2c_input_new) { // this is the start of a transaction, the first byte indicates the mode to be used
i2c_mode = input_data; // set user provided mode (no need to check since the undefined modes don't do anything)
i2c_input_new = false; // clear flag
// process mode switch
switch (i2c_mode) {
case MODE_CLEAR_DISPLAY: // clear display
hd44780_write_instruction(0x01); // clear display instruction
break;
case MODE_LINE1:
hd44780_write_instruction(0x80); // set DDRAM address to 0 (line 1)
break;
case MODE_LINE2:
hd44780_write_instruction(0xc0); // set DDRAM address to 0x40 (line 2)
break;
case MODE_DISPLAY_ON:
hd44780_write_instruction(0x0c); // display on
break;
case MODE_DISPLAY_OFF:
hd44780_write_instruction(0x08); // display off
break;
case MODE_RETURN_HOME:
hd44780_write_instruction(0x02); // return home
break;
default:
break; // waiting for data
}
} else {
// process data
// note set RS at every byte since read busy always switches it to instruction
switch (i2c_mode) {
case MODE_PORT:
case MODE_LINE1:
case MODE_LINE2:
case MODE_DATA:
hd44780_write_data(input_data);
break;
case MODE_ENTRY_MODE_SET:
hd44780_write_instruction(0x04 | (input_data & 0x3));
break;
case MODE_DISPLAY:
hd44780_write_instruction(0x08 | (input_data & 0x7));
break;
case MODE_CURSOR_DISPLAY_SHIFT:
hd44780_write_instruction(0x10 | (input_data & 0xc));
break;
case MODE_FUNCTION_SET:
hd44780_write_instruction(0x20 | (input_data & 0xc)); // keep DL=0 4-bit mode
break;
case MODE_CGRAM_ADDR:
hd44780_write_instruction(0x40 | (input_data & 0x3f));
break;
case MODE_DDRAM_ADDR:
hd44780_write_instruction(0x80 | (input_data & 0x3f));
break;
case MODE_BRIGHTNESS:
if (input_data) {
led_on();
} else {
led_off();
}
break;
case MODE_INSTRUCTION:
if (0x20 == (input_data & 0x20)) { // function set instruction
input_data &= ~(1 << 4); // ensure we stay in 4-bit mode
}
hd44780_write_instruction(input_data);
break;
case MODE_DATA:
hd44780_write_data(input_data);
break;
default: // read values do not make sense
break;
}