|
|
|
|
@@ -0,0 +1,311 @@
|
|
|
|
|
#include "../new_common.h"
|
|
|
|
|
#include "../new_pins.h"
|
|
|
|
|
#include "../new_cfg.h"
|
|
|
|
|
// Commands register, execution API and cmd tokenizer
|
|
|
|
|
#include "../cmnds/cmd_public.h"
|
|
|
|
|
#include "../mqtt/new_mqtt.h"
|
|
|
|
|
#include "../logging/logging.h"
|
|
|
|
|
#include "drv_local.h"
|
|
|
|
|
#include "drv_uart.h"
|
|
|
|
|
#include "../httpserver/new_http.h"
|
|
|
|
|
#include "../hal/hal_pins.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static softI2C_t g_softI2C;
|
|
|
|
|
|
|
|
|
|
static int ssd1306_addr = 0x3C;
|
|
|
|
|
|
|
|
|
|
#define SSD1306_CMD 0x00
|
|
|
|
|
#define SSD1306_DATA 0x40
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void SSD1306_WriteCmd(byte c) {
|
|
|
|
|
Soft_I2C_Start(&g_softI2C, ssd1306_addr << 1);
|
|
|
|
|
Soft_I2C_WriteByte(&g_softI2C, SSD1306_CMD);
|
|
|
|
|
Soft_I2C_WriteByte(&g_softI2C, c);
|
|
|
|
|
Soft_I2C_Stop(&g_softI2C);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void SSD1306_WriteData(byte d) {
|
|
|
|
|
Soft_I2C_Start(&g_softI2C, ssd1306_addr << 1);
|
|
|
|
|
Soft_I2C_WriteByte(&g_softI2C, SSD1306_DATA);
|
|
|
|
|
Soft_I2C_WriteByte(&g_softI2C, d);
|
|
|
|
|
Soft_I2C_Stop(&g_softI2C);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SSD1306_Fill(byte v) {
|
|
|
|
|
int i;
|
|
|
|
|
SSD1306_WriteCmd(0x21); // Set column range
|
|
|
|
|
SSD1306_WriteCmd(0x00);
|
|
|
|
|
SSD1306_WriteCmd(0x7F);
|
|
|
|
|
SSD1306_WriteCmd(0x22); // Set page range (for 128x32: 0-3)
|
|
|
|
|
SSD1306_WriteCmd(0x00);
|
|
|
|
|
SSD1306_WriteCmd(0x03);
|
|
|
|
|
for (i = 0; i < 512; i++)
|
|
|
|
|
SSD1306_WriteData(v);
|
|
|
|
|
}
|
|
|
|
|
void SSD1306_SetOn(bool b) {
|
|
|
|
|
if (b) {
|
|
|
|
|
SSD1306_WriteCmd(0xAF);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
SSD1306_WriteCmd(0xAE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
void SSD1306_SetPos(byte x, byte page) {
|
|
|
|
|
SSD1306_WriteCmd(0xB0 | page);
|
|
|
|
|
SSD1306_WriteCmd(0x00 | (x & 0x0F));
|
|
|
|
|
SSD1306_WriteCmd(0x10 | (x >> 4));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SSD1306_DrawRect(byte x, byte y, byte w, byte h, byte fill) {
|
|
|
|
|
byte px, py;
|
|
|
|
|
byte page_start = y >> 3;
|
|
|
|
|
byte page_end = (y + h - 1) >> 3;
|
|
|
|
|
|
|
|
|
|
for (py = page_start; py <= page_end; py++) {
|
|
|
|
|
SSD1306_SetPos(x, py);
|
|
|
|
|
for (px = 0; px < w; px++) {
|
|
|
|
|
|
|
|
|
|
byte mask = 0x00;
|
|
|
|
|
|
|
|
|
|
if (fill) {
|
|
|
|
|
mask = 0xFF;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (py == page_start || py == page_end)
|
|
|
|
|
mask = 0xFF;
|
|
|
|
|
else if (px == 0 || px == w - 1)
|
|
|
|
|
mask = 0xFF;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SSD1306_WriteData(mask);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Standard 5x7 ASCII font
|
|
|
|
|
static const byte font5x7[][5] = {
|
|
|
|
|
{0x00, 0x00, 0x00, 0x00, 0x00}, // space
|
|
|
|
|
{0x00, 0x00, 0x5F, 0x00, 0x00}, // !
|
|
|
|
|
{0x00, 0x07, 0x00, 0x07, 0x00}, // "
|
|
|
|
|
{0x14, 0x7F, 0x14, 0x7F, 0x14}, // #
|
|
|
|
|
{0x24, 0x2A, 0x7F, 0x2A, 0x12}, // $
|
|
|
|
|
{0x23, 0x13, 0x08, 0x64, 0x62}, // %
|
|
|
|
|
{0x36, 0x49, 0x55, 0x22, 0x50}, // &
|
|
|
|
|
{0x00, 0x05, 0x03, 0x00, 0x00}, // '
|
|
|
|
|
{0x00, 0x1C, 0x22, 0x41, 0x00}, // (
|
|
|
|
|
{0x00, 0x41, 0x22, 0x1C, 0x00}, // )
|
|
|
|
|
{0x14, 0x08, 0x3E, 0x08, 0x14}, // *
|
|
|
|
|
{0x08, 0x08, 0x3E, 0x08, 0x08}, // +
|
|
|
|
|
{0x00, 0x50, 0x60, 0x00, 0x00}, // ,
|
|
|
|
|
{0x08, 0x08, 0x08, 0x08, 0x08}, // -
|
|
|
|
|
{0x00, 0x60, 0x60, 0x00, 0x00}, // .
|
|
|
|
|
{0x20, 0x10, 0x08, 0x04, 0x02}, // /
|
|
|
|
|
{0x3E, 0x51, 0x49, 0x45, 0x3E}, // 0
|
|
|
|
|
{0x00, 0x42, 0x7F, 0x40, 0x00}, // 1
|
|
|
|
|
{0x42, 0x61, 0x51, 0x49, 0x46}, // 2
|
|
|
|
|
{0x21, 0x41, 0x45, 0x4B, 0x31}, // 3
|
|
|
|
|
{0x18, 0x14, 0x12, 0x7F, 0x10}, // 4
|
|
|
|
|
{0x27, 0x45, 0x45, 0x45, 0x39}, // 5
|
|
|
|
|
{0x3C, 0x4A, 0x49, 0x49, 0x30}, // 6
|
|
|
|
|
{0x01, 0x71, 0x09, 0x05, 0x03}, // 7
|
|
|
|
|
{0x36, 0x49, 0x49, 0x49, 0x36}, // 8
|
|
|
|
|
{0x06, 0x49, 0x49, 0x29, 0x1E}, // 9
|
|
|
|
|
{0x00, 0x36, 0x36, 0x00, 0x00}, // :
|
|
|
|
|
{0x00, 0x56, 0x36, 0x00, 0x00}, // ;
|
|
|
|
|
{0x08, 0x14, 0x22, 0x41, 0x00}, // <
|
|
|
|
|
{0x14, 0x14, 0x14, 0x14, 0x14}, // =
|
|
|
|
|
{0x00, 0x41, 0x22, 0x14, 0x08}, // >
|
|
|
|
|
{0x02, 0x01, 0x51, 0x09, 0x06}, // ?
|
|
|
|
|
{0x32, 0x49, 0x79, 0x41, 0x3E}, // @
|
|
|
|
|
{0x7E, 0x11, 0x11, 0x11, 0x7E}, // A
|
|
|
|
|
{0x7F, 0x49, 0x49, 0x49, 0x36}, // B
|
|
|
|
|
{0x3E, 0x41, 0x41, 0x41, 0x22}, // C
|
|
|
|
|
{0x7F, 0x41, 0x41, 0x22, 0x1C}, // D
|
|
|
|
|
{0x7F, 0x49, 0x49, 0x49, 0x41}, // E
|
|
|
|
|
{0x7F, 0x09, 0x09, 0x09, 0x01}, // F
|
|
|
|
|
{0x3E, 0x41, 0x49, 0x49, 0x7A}, // G
|
|
|
|
|
{0x7F, 0x08, 0x08, 0x08, 0x7F}, // H
|
|
|
|
|
{0x00, 0x41, 0x7F, 0x41, 0x00}, // I
|
|
|
|
|
{0x20, 0x40, 0x41, 0x3F, 0x01}, // J
|
|
|
|
|
{0x7F, 0x08, 0x14, 0x22, 0x41}, // K
|
|
|
|
|
{0x7F, 0x40, 0x40, 0x40, 0x40}, // L
|
|
|
|
|
{0x7F, 0x02, 0x0C, 0x02, 0x7F}, // M
|
|
|
|
|
{0x7F, 0x04, 0x08, 0x10, 0x7F}, // N
|
|
|
|
|
{0x3E, 0x41, 0x41, 0x41, 0x3E}, // O
|
|
|
|
|
{0x7F, 0x09, 0x09, 0x09, 0x06}, // P
|
|
|
|
|
{0x3E, 0x41, 0x51, 0x21, 0x5E}, // Q
|
|
|
|
|
{0x7F, 0x09, 0x19, 0x29, 0x46}, // R
|
|
|
|
|
{0x46, 0x49, 0x49, 0x49, 0x31}, // S
|
|
|
|
|
{0x01, 0x01, 0x7F, 0x01, 0x01}, // T
|
|
|
|
|
{0x3F, 0x40, 0x40, 0x40, 0x3F}, // U
|
|
|
|
|
{0x1F, 0x20, 0x40, 0x20, 0x1F}, // V
|
|
|
|
|
{0x3F, 0x40, 0x38, 0x40, 0x3F}, // W
|
|
|
|
|
{0x63, 0x14, 0x08, 0x14, 0x63}, // X
|
|
|
|
|
{0x07, 0x08, 0x70, 0x08, 0x07}, // Y
|
|
|
|
|
{0x61, 0x51, 0x49, 0x45, 0x43}, // Z
|
|
|
|
|
};
|
|
|
|
|
void SSD1306_WriteChar(char c) {
|
|
|
|
|
// Convert lowercase to uppercase
|
|
|
|
|
if (c >= 'a' && c <= 'z') {
|
|
|
|
|
c = c - 'a' + 'A';
|
|
|
|
|
}
|
|
|
|
|
if (c < 32 || c > 90) c = 32; // Basic bounds check, map unknown to space
|
|
|
|
|
c -= 32; // Offset to match array index
|
|
|
|
|
|
|
|
|
|
Soft_I2C_Start(&g_softI2C, ssd1306_addr << 1);
|
|
|
|
|
Soft_I2C_WriteByte(&g_softI2C, SSD1306_DATA);
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 5; i++) {
|
|
|
|
|
Soft_I2C_WriteByte(&g_softI2C, font5x7[(uint8_t)c][i]);
|
|
|
|
|
}
|
|
|
|
|
Soft_I2C_WriteByte(&g_softI2C, 0x00); // 1px spacing between chars
|
|
|
|
|
Soft_I2C_Stop(&g_softI2C);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SSD1306_String(const char *str) {
|
|
|
|
|
while (*str) {
|
|
|
|
|
SSD1306_WriteChar(*str++);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//int x = 1000;
|
|
|
|
|
void SSD1306_OnEverySecond() {
|
|
|
|
|
//SSD1306_SetOn(true);
|
|
|
|
|
//x++;
|
|
|
|
|
//char tmp[8];
|
|
|
|
|
//sprintf(tmp, "%i", x);
|
|
|
|
|
//SSD1306_SetPos(0, 0);
|
|
|
|
|
//SSD1306_String(tmp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
commandResult_t SSD1306_Cmd_Print(const void* context, const char* cmd, const char* args, int cmdFlags) {
|
|
|
|
|
Tokenizer_TokenizeString(args, TOKENIZER_ALLOW_QUOTES);
|
|
|
|
|
// following check must be done after 'Tokenizer_TokenizeString',
|
|
|
|
|
// so we know arguments count in Tokenizer. 'cmd' argument is
|
|
|
|
|
// only for warning display
|
|
|
|
|
if (Tokenizer_CheckArgsCountAndPrintWarning(cmd, 1)) {
|
|
|
|
|
return CMD_RES_NOT_ENOUGH_ARGUMENTS;
|
|
|
|
|
}
|
|
|
|
|
const char *s = Tokenizer_GetArg(0);
|
|
|
|
|
SSD1306_String(s);
|
|
|
|
|
return CMD_RES_OK;
|
|
|
|
|
}
|
|
|
|
|
commandResult_t SSD1306_Cmd_GoTo(const void* context, const char* cmd, const char* args, int cmdFlags) {
|
|
|
|
|
Tokenizer_TokenizeString(args, TOKENIZER_ALLOW_QUOTES);
|
|
|
|
|
// following check must be done after 'Tokenizer_TokenizeString',
|
|
|
|
|
// so we know arguments count in Tokenizer. 'cmd' argument is
|
|
|
|
|
// only for warning display
|
|
|
|
|
if (Tokenizer_CheckArgsCountAndPrintWarning(cmd, 2)) {
|
|
|
|
|
return CMD_RES_NOT_ENOUGH_ARGUMENTS;
|
|
|
|
|
}
|
|
|
|
|
int x = Tokenizer_GetArgInteger(0);
|
|
|
|
|
int y = Tokenizer_GetArgInteger(1);
|
|
|
|
|
SSD1306_SetPos(x, y);
|
|
|
|
|
return CMD_RES_OK;
|
|
|
|
|
}
|
|
|
|
|
commandResult_t SSD1306_Cmd_On(const void* context, const char* cmd, const char* args, int cmdFlags) {
|
|
|
|
|
Tokenizer_TokenizeString(args, 0);
|
|
|
|
|
// following check must be done after 'Tokenizer_TokenizeString',
|
|
|
|
|
// so we know arguments count in Tokenizer. 'cmd' argument is
|
|
|
|
|
// only for warning display
|
|
|
|
|
if (Tokenizer_CheckArgsCountAndPrintWarning(cmd, 1)) {
|
|
|
|
|
return CMD_RES_NOT_ENOUGH_ARGUMENTS;
|
|
|
|
|
}
|
|
|
|
|
int bOn = Tokenizer_GetArgInteger(0);
|
|
|
|
|
SSD1306_SetOn(bOn);
|
|
|
|
|
return CMD_RES_OK;
|
|
|
|
|
}
|
|
|
|
|
commandResult_t SSD1306_Cmd_Clear(const void* context, const char* cmd, const char* args, int cmdFlags) {
|
|
|
|
|
Tokenizer_TokenizeString(args, 0);
|
|
|
|
|
// following check must be done after 'Tokenizer_TokenizeString',
|
|
|
|
|
// so we know arguments count in Tokenizer. 'cmd' argument is
|
|
|
|
|
// only for warning display
|
|
|
|
|
if (Tokenizer_CheckArgsCountAndPrintWarning(cmd, 1)) {
|
|
|
|
|
return CMD_RES_NOT_ENOUGH_ARGUMENTS;
|
|
|
|
|
}
|
|
|
|
|
int val = Tokenizer_GetArgInteger(0);
|
|
|
|
|
SSD1306_Fill(val);
|
|
|
|
|
return CMD_RES_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SSD1306_Cmd_Rect(const void* context, const char* cmd, const char* args, int cmdFlags) {
|
|
|
|
|
Tokenizer_TokenizeString(args, 0);
|
|
|
|
|
// following check must be done after 'Tokenizer_TokenizeString',
|
|
|
|
|
// so we know arguments count in Tokenizer. 'cmd' argument is
|
|
|
|
|
// only for warning display
|
|
|
|
|
if (Tokenizer_CheckArgsCountAndPrintWarning(cmd, 4)) {
|
|
|
|
|
return CMD_RES_NOT_ENOUGH_ARGUMENTS;
|
|
|
|
|
}
|
|
|
|
|
int x = Tokenizer_GetArgInteger(0);
|
|
|
|
|
int y = Tokenizer_GetArgInteger(1);
|
|
|
|
|
int w = Tokenizer_GetArgInteger(2);
|
|
|
|
|
int h = Tokenizer_GetArgInteger(3);
|
|
|
|
|
int fill = Tokenizer_GetArgIntegerDefault(4, 0xff);
|
|
|
|
|
SSD1306_DrawRect(x, y, w, h, fill);
|
|
|
|
|
return CMD_RES_OK;
|
|
|
|
|
}
|
|
|
|
|
// startDriver SSD1306 16 20 0x3C
|
|
|
|
|
// backlog stopdriver SSD1306 ; startDriver SSD1306 16 20 0x3C
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
backlog stopdriver SSD1306 ; startDriver SSD1306 16 20 0x3C
|
|
|
|
|
ssd1306_clear 0
|
|
|
|
|
ssd1306_on 1
|
|
|
|
|
setChannel 12 0
|
|
|
|
|
again:
|
|
|
|
|
delay_s 1
|
|
|
|
|
ssd1306_goto 0 0
|
|
|
|
|
ssd1306_print "Hello "
|
|
|
|
|
ssd1306_print $CH12
|
|
|
|
|
addChannel 12 1
|
|
|
|
|
goto again
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
void SSD1306_Init() {
|
|
|
|
|
|
|
|
|
|
g_softI2C.pin_clk = Tokenizer_GetPin(1, 16);
|
|
|
|
|
g_softI2C.pin_data = Tokenizer_GetPin(2, 20);
|
|
|
|
|
ssd1306_addr = Tokenizer_GetArgIntegerDefault(3, 0x3C);
|
|
|
|
|
|
|
|
|
|
CMD_RegisterCommand("ssd1306_clear", SSD1306_Cmd_Clear, NULL);
|
|
|
|
|
CMD_RegisterCommand("ssd1306_on", SSD1306_Cmd_On, NULL);
|
|
|
|
|
CMD_RegisterCommand("ssd1306_print", SSD1306_Cmd_Print, NULL);
|
|
|
|
|
CMD_RegisterCommand("ssd1306_rect", SSD1306_Cmd_Rect, NULL);
|
|
|
|
|
CMD_RegisterCommand("ssd1306_goto", SSD1306_Cmd_GoTo, NULL);
|
|
|
|
|
|
|
|
|
|
Soft_I2C_PreInit(&g_softI2C);
|
|
|
|
|
|
|
|
|
|
SSD1306_WriteCmd(0xAE);
|
|
|
|
|
SSD1306_WriteCmd(0xD5);
|
|
|
|
|
SSD1306_WriteCmd(0x80);
|
|
|
|
|
SSD1306_WriteCmd(0xA8);
|
|
|
|
|
SSD1306_WriteCmd(0x1F);
|
|
|
|
|
SSD1306_WriteCmd(0xD3);
|
|
|
|
|
SSD1306_WriteCmd(0x00);
|
|
|
|
|
SSD1306_WriteCmd(0x40);
|
|
|
|
|
SSD1306_WriteCmd(0x8D);
|
|
|
|
|
SSD1306_WriteCmd(0x14);
|
|
|
|
|
SSD1306_WriteCmd(0x20);
|
|
|
|
|
SSD1306_WriteCmd(0x00);
|
|
|
|
|
SSD1306_WriteCmd(0xA1);
|
|
|
|
|
SSD1306_WriteCmd(0xC8);
|
|
|
|
|
SSD1306_WriteCmd(0xDA);
|
|
|
|
|
SSD1306_WriteCmd(0x02);
|
|
|
|
|
SSD1306_WriteCmd(0x81);
|
|
|
|
|
SSD1306_WriteCmd(0x8F);
|
|
|
|
|
SSD1306_WriteCmd(0xD9);
|
|
|
|
|
SSD1306_WriteCmd(0xF1);
|
|
|
|
|
SSD1306_WriteCmd(0xDB);
|
|
|
|
|
SSD1306_WriteCmd(0x40);
|
|
|
|
|
SSD1306_WriteCmd(0xA4);
|
|
|
|
|
SSD1306_WriteCmd(0xA6);
|
|
|
|
|
SSD1306_WriteCmd(0xAF);
|
|
|
|
|
|
|
|
|
|
SSD1306_Fill(0x00);
|
|
|
|
|
}
|