#include <string.h>
typedef unsigned int uint;
+typedef uint8_t byte;
typedef uint16_t u16;
typedef int16_t s16;
va_end(args);
}
+#if 0
+
static uint bmp_read(uint reg, uint bytes)
{
LL_I2C_ClearFlag_STOP(I2C1);
LL_mDelay(1000);
}
}
+
+#else
+
+// Based on https://github.com/adafruit/Adafruit_SSD1306
+
+#define SSD1306_SETLOWCOLUMN 0x00
+#define SSD1306_SETHIGHCOLUMN 0x10
+#define SSD1306_MEMORYMODE 0x20
+#define SSD1306_SETSTARTLINE 0x40
+#define SSD1306_SETCONTRAST 0x81
+#define SSD1306_CHARGEPUMP 0x8D
+#define SSD1306_SEGREMAP 0xA0
+#define SSD1306_DISPLAYALLON_RESUME 0xA4
+#define SSD1306_DISPLAYALLON 0xA5
+#define SSD1306_NORMALDISPLAY 0xA6
+#define SSD1306_INVERTDISPLAY 0xA7
+#define SSD1306_SETMULTIPLEX 0xA8
+#define SSD1306_DISPLAYOFF 0xAE
+#define SSD1306_DISPLAYON 0xAF
+#define SSD1306_SETSTARTPAGE 0xB0
+#define SSD1306_COMSCANINC 0xC0
+#define SSD1306_COMSCANDEC 0xC8
+#define SSD1306_SETDISPLAYOFFSET 0xD3
+#define SSD1306_SETCOMPINS 0xDA
+#define SSD1306_SETVCOMDETECT 0xDB
+#define SSD1306_SETDISPLAYCLOCKDIV 0xD5
+#define SSD1306_SETPRECHARGE 0xD9
+#define SSD1306_NOP 0xE3
+
+static const byte display_init_cmds[] = {
+ SSD1306_DISPLAYOFF,
+ SSD1306_SETDISPLAYCLOCKDIV, 0x80, // the suggested ratio 0x80
+ SSD1306_SETMULTIPLEX, 0x1F, // ratio 32
+ SSD1306_SETDISPLAYOFFSET,0x0, // no offset
+ SSD1306_SETSTARTLINE | 0x0, // line #0
+ SSD1306_CHARGEPUMP, 0x14, // internal vcc
+ SSD1306_MEMORYMODE, 0x02, // page mode
+ SSD1306_SEGREMAP | 0x0, // column 0 mapped to SEG0
+ SSD1306_COMSCANDEC, // column scan direction reversed
+ SSD1306_SETCOMPINS, 0x02, // sequential COM pins, disable remap
+ SSD1306_SETCONTRAST, 0x7F, // contrast level 127
+ SSD1306_SETPRECHARGE, 0xF1, // pre-charge period (1, 15)
+ SSD1306_SETVCOMDETECT, 0x40, // vcomh regulator level-
+ SSD1306_DISPLAYALLON_RESUME,
+ SSD1306_NORMALDISPLAY,
+ SSD1306_DISPLAYON,
+};
+
+static void display_cmd(byte cmd)
+{
+ LL_I2C_ClearFlag_STOP(I2C1);
+ LL_I2C_HandleTransfer(I2C1, 0x79, LL_I2C_ADDRSLAVE_7BIT, 2, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_WRITE);
+ while (!LL_I2C_IsActiveFlag_TXE(I2C1))
+ ;
+ LL_I2C_TransmitData8(I2C1, 0x00); // Will send a command
+ while (!LL_I2C_IsActiveFlag_TXE(I2C1))
+ ;
+ LL_I2C_TransmitData8(I2C1, cmd);
+ while (!LL_I2C_IsActiveFlag_STOP(I2C1))
+ ;
+}
+
+static void display_data_start(uint cnt)
+{
+ LL_I2C_ClearFlag_STOP(I2C1);
+ LL_I2C_HandleTransfer(I2C1, 0x79, LL_I2C_ADDRSLAVE_7BIT, cnt + 1, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_WRITE);
+ while (!LL_I2C_IsActiveFlag_TXE(I2C1))
+ ;
+ LL_I2C_TransmitData8(I2C1, 0x40); // Will send data
+}
+
+static void display_data(byte d)
+{
+ while (!LL_I2C_IsActiveFlag_TXE(I2C1))
+ ;
+ LL_I2C_TransmitData8(I2C1, d);
+}
+
+static void display_data_end(void)
+{
+ while (!LL_I2C_IsActiveFlag_STOP(I2C1))
+ ;
+}
+
+static void display_init(void)
+{
+ for (uint i=0; i < sizeof(display_init_cmds); i++)
+ display_cmd(display_init_cmds[i]);
+
+ for (uint p=0; p<4; p++)
+ {
+ display_cmd(SSD1306_SETSTARTPAGE + p);
+ display_cmd(SSD1306_SETHIGHCOLUMN);
+ display_cmd(SSD1306_SETLOWCOLUMN);
+ display_data_start(128);
+ for (uint i=0; i<128; i++)
+ display_data(p == 0 ? 0x80 | i : 0);
+ display_data_end();
+ }
+}
+
+void run_test(void)
+{
+ uint cnt = 0;
+
+ debug_puts("Init\r\n");
+ display_init();
+
+ for (;;)
+ {
+ LL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
+
+ debug_printf("Tick tock: %d\r\n", cnt);
+
+ LL_mDelay(1000);
+ cnt++;
+ }
+}
+
+#endif