From 61681b06776d08b8566523f5808ed7af28856102 Mon Sep 17 00:00:00 2001 From: destroyedlolo Date: Sun, 8 Sep 2024 01:06:53 +0200 Subject: [PATCH 01/19] Start with LCD module --- remake.sh | 27 +++++++++-- src/SelPlugins/LCD/SelLCD.c | 62 ++++++++++++++++++++++++++ src/include/Selene/SelPlug-in/SelLCD.h | 24 ++++++++++ 3 files changed, 110 insertions(+), 3 deletions(-) create mode 100644 src/SelPlugins/LCD/SelLCD.c create mode 100644 src/include/Selene/SelPlug-in/SelLCD.h diff --git a/remake.sh b/remake.sh index 76227de..2cbc15c 100644 --- a/remake.sh +++ b/remake.sh @@ -11,7 +11,10 @@ USE_CURSES=1 # Build OLED screen plug-in -# USE_OLED=1 +USE_OLED=1 + +# Build LCD1602 plug-in +USE_LCD=1 # Build DRMCairo plug-in USE_DRMCAIRO=1 @@ -37,9 +40,9 @@ DRMC_WITH_FB=1 # where to install plugins # production -PLUGIN_DIR=/usr/local/lib +# PLUGIN_DIR=/usr/local/lib # for development -# PLUGIN_DIR=$( pwd )/lib +PLUGIN_DIR=$( pwd )/lib if [ ${PLUGIN_DIR+x} ] then @@ -194,6 +197,24 @@ else fi +echo +echo "LCD plug-in" +echo "-----------" + +if [ ${USE_LCD+x} ]; then + echo "LCD used" + USE_LCD="-DUSE_LCD" + + cd src/SelPlugins/LCD/ + LFMakeMaker -v +f=Makefile --opts="-I../../include $CFLAGS $DEBUG $MCHECK $LUA $USE_LCD " *.c -so=../../../lib/Selene/SelLCD.so > Makefile + cd ../../.. + + echo -e '\t$(MAKE) -C src/SelPlugins/LCD' >> Makefile +else + echo "LCD not used" +fi + + echo echo "DRMCairo plugin" echo "---------------" diff --git a/src/SelPlugins/LCD/SelLCD.c b/src/SelPlugins/LCD/SelLCD.c new file mode 100644 index 0000000..6e0e075 --- /dev/null +++ b/src/SelPlugins/LCD/SelLCD.c @@ -0,0 +1,62 @@ +/*** + * Display messages on an LCD textual screen (like 1602 one) + +@classmod SelOLED + + * 06/09/2024 LF : First version + */ + +#include +#include +#include + +static struct SelLCD selLCD; + +static struct SeleneCore *selCore; +static struct SelLog *selLog; +static struct SelLua *selLua; + +struct LCDscreen { + int bus; /* I2C bus file descriptor */ + bool backlight; /* is backlight enabled */ +}; + +static const struct luaL_Reg LCDLib[] = { + {NULL, NULL} /* End of definition */ +}; + +static void registerSelLCD(lua_State *L){ + selLua->libCreateOrAddFuncs(L, "SelLCD", LCDLib); +} + +/* *** + * This function MUST exist and is called when the module is loaded. + * Its goal is to initialize module's configuration and register the module. + * If needed, it can also do some internal initialisation work for the module. + * ***/ +bool InitModule( void ){ + /* Core modules */ + selCore = (struct SeleneCore *)findModuleByName("SeleneCore", SELENECORE_VERSION); + if(!selCore) + return false; + + selLog = (struct SelLog *)selCore->findModuleByName("SelLog", SELLOG_VERSION,'F'); + if(!selLog) + return false; + + /* Other mandatory modules */ + selLua = (struct SelLua *)selCore->findModuleByName("SelLua", SELLUA_VERSION,0); + + /* optional modules */ + + /* Initialise module's glue */ + if(!initModule((struct SelModule *)&selLCD, "SelLCD", SELLCD_VERSION, LIBSELENE_VERSION)) + return false; + + registerModule((struct SelModule *)&selLCD); + + registerSelLCD(NULL); + selLua->AddStartupFunc(registerSelLCD); + + return true; +} diff --git a/src/include/Selene/SelPlug-in/SelLCD.h b/src/include/Selene/SelPlug-in/SelLCD.h new file mode 100644 index 0000000..e068a0e --- /dev/null +++ b/src/include/Selene/SelPlug-in/SelLCD.h @@ -0,0 +1,24 @@ +/* SelLCD.h + * + * Display messages on an LCD textual screen (like 1602 one) + * + * Have a look and respect Selene Licence. + */ + +#ifndef SELLCD_VERSION + +#include +#include + +/* *********** + * /!\ CAUTION : BUMP THIS VERSION AT EVERY CHANGE INSIDE GLUE STRUCTURE + * ***********/ +#define SELLCD_VERSION 2 + +struct SelLCD { + struct SelModule module; + + /* Call backs */ +}; + +#endif From 2e9505c807752e9a833f52a93ac6982b9e7239ba Mon Sep 17 00:00:00 2001 From: destroyedlolo Date: Sun, 8 Sep 2024 15:51:33 +0200 Subject: [PATCH 02/19] Add lowlevels --- src/SelPlugins/LCD/SelLCD.c | 115 ++++++++++++++++++++++++- src/include/Selene/SelPlug-in/SelLCD.h | 14 +++ 2 files changed, 125 insertions(+), 4 deletions(-) diff --git a/src/SelPlugins/LCD/SelLCD.c b/src/SelPlugins/LCD/SelLCD.c index 6e0e075..8841cd9 100644 --- a/src/SelPlugins/LCD/SelLCD.c +++ b/src/SelPlugins/LCD/SelLCD.c @@ -1,5 +1,8 @@ /*** * Display messages on an LCD textual screen (like 1602 one) + * + * Based on https://fr.wikipedia.org/wiki/HD44780 + * and inspired by BitBank https://github.com/bitbank2/LCD1602 @classmod SelOLED @@ -10,16 +13,115 @@ #include #include +#include +#include +#include + static struct SelLCD selLCD; static struct SeleneCore *selCore; static struct SelLog *selLog; static struct SelLua *selLua; -struct LCDscreen { - int bus; /* I2C bus file descriptor */ - bool backlight; /* is backlight enabled */ -}; +/* I2C expender bits usage : + * + * 0 : RS (0 = command, 1 = data) + * 1 : Read (0) / Write (1) + * 2 : Enable + * 3 : Backlight + */ +#define RS_CMD 0 +#define RS_DATA 0x01 +#define RW_R 0 +#define RW_W 0x02 +#define ENABLE 0x04 +#define BACKLIGHT 0x08 + +static void SendQuarter(struct LCDscreen *screen, uint8_t b){ +/* Send the provided quarter */ + + write(screen->bus, &b, 1); /* Present the data on the gpio */ + usleep(selLCD.clock_pulse); + + b |= ENABLE; /* Rise 'E' */ + write(screen->bus, &b, 1); + usleep(selLCD.clock_pulse); + + b &= ~(ENABLE); /* Lower 'E' */ + write(screen->bus, &b, 1); + usleep(selLCD.clock_process); +} + +static void lcdc_SendCmd(struct LCDscreen *screen, uint8_t dt){ +/** + * @brief Send a command to the LCD controller + * + * @function SendCmd + * @tparam uint8_t command to send + */ + uint8_t t = RS_CMD; /* It's a Command */ + t |= screen->backlight ? BACKLIGHT : 0; /* Is the backlight on ? */ + + /* Most significant quarter first */ + t |= dt & 0xf0; + SendQuarter(screen, t); + + t &= 0x0f; /* Keep only control bits */ + t |= dt << 4; /* send less significant quarter */ + SendQuarter(screen, t); +} + +static void lcdc_SendData(struct LCDscreen *screen, uint8_t dt){ +/** + * @brief Send a data to the LCD controller + * + * @function SendData + * @tparam uint8_t data to send + */ + uint8_t t = RS_DATA; /* It's a Command */ + t |= screen->backlight ? BACKLIGHT : 0; /* Is the backlight on ? */ + + /* Most significant quarter first */ + t |= dt & 0xf0; + SendQuarter(screen, t); + + t &= 0x0f; /* Keep only control bits */ + t |= dt << 4; /* send less significant quarter */ + SendQuarter(screen, t); +} + +static bool lcdc_Init(struct LCDscreen *screen, uint16_t bus_number, uint8_t address, bool twolines, bool y11){ +/** + * @brief Initialize connection to the screen + * + * @function Init + * @param screen point to the screen handle + * @tparam uint16_t I2C bus number + * @tparam uint8_t Screen I2C address + * @tparam boolean true if the screen has 2 lines + * @tparam boolean true if the screen is 11 pixel hight + * @treturn boolean false if we faced a technical error + */ + char sbus[16]; + sprintf(sbus, "/dev/i2c-%u", bus_number); + + if((screen->bus = open(sbus, O_RDWR)) < 0) + return false; + + if(ioctl(screen->bus, I2C_SLAVE, address) < 0) + return false; + + /* Initializing + * SET + 4 bits mode + * We're sending the upper quarter first so 0x02 is really 0x20. + */ + selLCD.SendCmd(screen, 0x02); + + /* Now sending the full configuration */ + selLCD.SendCmd(screen, 0x02 | (twolines ? 0x08 : 0) | (y11 ? 0x04 : 0)); + + return true; +} static const struct luaL_Reg LCDLib[] = { {NULL, NULL} /* End of definition */ @@ -58,5 +160,10 @@ bool InitModule( void ){ registerSelLCD(NULL); selLua->AddStartupFunc(registerSelLCD); + /* Callbacks */ + selLCD.Init = lcdc_Init; + selLCD.SendCmd = lcdc_SendCmd; + selLCD.SendData = lcdc_SendData; + return true; } diff --git a/src/include/Selene/SelPlug-in/SelLCD.h b/src/include/Selene/SelPlug-in/SelLCD.h index e068a0e..5019e24 100644 --- a/src/include/Selene/SelPlug-in/SelLCD.h +++ b/src/include/Selene/SelPlug-in/SelLCD.h @@ -10,15 +10,29 @@ #include #include +#include + /* *********** * /!\ CAUTION : BUMP THIS VERSION AT EVERY CHANGE INSIDE GLUE STRUCTURE * ***********/ #define SELLCD_VERSION 2 +struct LCDscreen { + int bus; /* I2C bus file descriptor */ + bool backlight; /* is backlight enabled */ +}; + struct SelLCD { struct SelModule module; + useconds_t clock_pulse; /* 'E' clock */ + useconds_t clock_process; /* time to process */ + /* Call backs */ + bool (*Init)(struct LCDscreen *, uint16_t bus_number, uint8_t address, bool twolines, bool y11); + + void (*SendCmd)(struct LCDscreen *, uint8_t); + void (*SendData)(struct LCDscreen *, uint8_t); }; #endif From 20d93c43c856349959383fcb70aab24637549434 Mon Sep 17 00:00:00 2001 From: destroyedlolo Date: Sun, 8 Sep 2024 16:21:07 +0200 Subject: [PATCH 03/19] Add EntryCtl --- src/SelPlugins/LCD/SelLCD.c | 70 +++++++++++++++++++------- src/include/Selene/SelPlug-in/SelLCD.h | 5 +- src/include/Selene/SeleneVersion.h | 4 +- 3 files changed, 60 insertions(+), 19 deletions(-) diff --git a/src/SelPlugins/LCD/SelLCD.c b/src/SelPlugins/LCD/SelLCD.c index 8841cd9..6b7af70 100644 --- a/src/SelPlugins/LCD/SelLCD.c +++ b/src/SelPlugins/LCD/SelLCD.c @@ -37,22 +37,22 @@ static struct SelLua *selLua; #define ENABLE 0x04 #define BACKLIGHT 0x08 -static void SendQuarter(struct LCDscreen *screen, uint8_t b){ +static void SendQuarter(struct LCDscreen *lcd, uint8_t b){ /* Send the provided quarter */ - write(screen->bus, &b, 1); /* Present the data on the gpio */ + write(lcd->bus, &b, 1); /* Present the data on the gpio */ usleep(selLCD.clock_pulse); b |= ENABLE; /* Rise 'E' */ - write(screen->bus, &b, 1); + write(lcd->bus, &b, 1); usleep(selLCD.clock_pulse); b &= ~(ENABLE); /* Lower 'E' */ - write(screen->bus, &b, 1); + write(lcd->bus, &b, 1); usleep(selLCD.clock_process); } -static void lcdc_SendCmd(struct LCDscreen *screen, uint8_t dt){ +static void lcdc_SendCmd(struct LCDscreen *lcd, uint8_t dt){ /** * @brief Send a command to the LCD controller * @@ -60,18 +60,18 @@ static void lcdc_SendCmd(struct LCDscreen *screen, uint8_t dt){ * @tparam uint8_t command to send */ uint8_t t = RS_CMD; /* It's a Command */ - t |= screen->backlight ? BACKLIGHT : 0; /* Is the backlight on ? */ + t |= lcd->backlight ? BACKLIGHT : 0; /* Is the backlight on ? */ /* Most significant quarter first */ t |= dt & 0xf0; - SendQuarter(screen, t); + SendQuarter(lcd, t); t &= 0x0f; /* Keep only control bits */ t |= dt << 4; /* send less significant quarter */ - SendQuarter(screen, t); + SendQuarter(lcd, t); } -static void lcdc_SendData(struct LCDscreen *screen, uint8_t dt){ +static void lcdc_SendData(struct LCDscreen *lcd, uint8_t dt){ /** * @brief Send a data to the LCD controller * @@ -79,18 +79,18 @@ static void lcdc_SendData(struct LCDscreen *screen, uint8_t dt){ * @tparam uint8_t data to send */ uint8_t t = RS_DATA; /* It's a Command */ - t |= screen->backlight ? BACKLIGHT : 0; /* Is the backlight on ? */ + t |= lcd->backlight ? BACKLIGHT : 0; /* Is the backlight on ? */ /* Most significant quarter first */ t |= dt & 0xf0; - SendQuarter(screen, t); + SendQuarter(lcd, t); t &= 0x0f; /* Keep only control bits */ t |= dt << 4; /* send less significant quarter */ - SendQuarter(screen, t); + SendQuarter(lcd, t); } -static bool lcdc_Init(struct LCDscreen *screen, uint16_t bus_number, uint8_t address, bool twolines, bool y11){ +static bool lcdc_Init(struct LCDscreen *lcd, uint16_t bus_number, uint8_t address, bool twolines, bool y11){ /** * @brief Initialize connection to the screen * @@ -105,24 +105,58 @@ static bool lcdc_Init(struct LCDscreen *screen, uint16_t bus_number, uint8_t add char sbus[16]; sprintf(sbus, "/dev/i2c-%u", bus_number); - if((screen->bus = open(sbus, O_RDWR)) < 0) + if((lcd->bus = open(sbus, O_RDWR)) < 0) return false; - if(ioctl(screen->bus, I2C_SLAVE, address) < 0) + if(ioctl(lcd->bus, I2C_SLAVE, address) < 0) return false; /* Initializing * SET + 4 bits mode * We're sending the upper quarter first so 0x02 is really 0x20. */ - selLCD.SendCmd(screen, 0x02); + selLCD.SendCmd(lcd, 0x02); /* Now sending the full configuration */ - selLCD.SendCmd(screen, 0x02 | (twolines ? 0x08 : 0) | (y11 ? 0x04 : 0)); + selLCD.SendCmd(lcd, 0x02 | (twolines ? 0x08 : 0) | (y11 ? 0x04 : 0)); return true; } +static void lcdc_DisplayCtl(struct LCDscreen *lcd, bool screen, bool cursor, bool blink){ +/** + * @brief Display control + * + * @function DisplayCtl + * @param screen point to the screen handle + * @tparam boolean is the screen on ? + * @tparam boolean is the _ cursor on ? + * @tparam boolean is the block cursor on ? + */ + uint8_t t = 0x08; /* Display control */ + t |= screen ? 0x04:0x00; + t |= cursor ? 0x02:0x00; + t |= blink ? 0x01:0x00; + + selLCD.SendCmd(lcd, t); +} + +static void lcdc_EntryCtl(struct LCDscreen *lcd, bool inc, bool shift){ +/** + * @brief Entry control + * + * @function EntryCtl + * @param screen point to the screen handle + * @tparam boolean increment the cursor when a character is sent + * @tparam boolean shift the screen if the cursor leaves it + */ + uint8_t t = 0x04; /* Enty control */ + t |= inc ? 0x02 : 0x00; + t |= shift ? 0x01 : 0x00; + + selLCD.SendCmd(lcd, t); +} + static const struct luaL_Reg LCDLib[] = { {NULL, NULL} /* End of definition */ }; @@ -164,6 +198,8 @@ bool InitModule( void ){ selLCD.Init = lcdc_Init; selLCD.SendCmd = lcdc_SendCmd; selLCD.SendData = lcdc_SendData; + selLCD.DisplayCtl = lcdc_DisplayCtl; + selLCD.EntryCtl = lcdc_EntryCtl; return true; } diff --git a/src/include/Selene/SelPlug-in/SelLCD.h b/src/include/Selene/SelPlug-in/SelLCD.h index 5019e24..a57f8e0 100644 --- a/src/include/Selene/SelPlug-in/SelLCD.h +++ b/src/include/Selene/SelPlug-in/SelLCD.h @@ -15,7 +15,7 @@ /* *********** * /!\ CAUTION : BUMP THIS VERSION AT EVERY CHANGE INSIDE GLUE STRUCTURE * ***********/ -#define SELLCD_VERSION 2 +#define SELLCD_VERSION 1 struct LCDscreen { int bus; /* I2C bus file descriptor */ @@ -33,6 +33,9 @@ struct SelLCD { void (*SendCmd)(struct LCDscreen *, uint8_t); void (*SendData)(struct LCDscreen *, uint8_t); + + void (*DisplayCtl)(struct LCDscreen *, bool screen, bool cursor, bool blink); + void (*EntryCtl)(struct LCDscreen *, bool inc, bool shift); }; #endif diff --git a/src/include/Selene/SeleneVersion.h b/src/include/Selene/SeleneVersion.h index 20ea3c1..40df354 100644 --- a/src/include/Selene/SeleneVersion.h +++ b/src/include/Selene/SeleneVersion.h @@ -55,7 +55,9 @@ * 09/03/2020 LF : v6.11.00 - Use StartupFunc to declare objects in slave threads * * 06/02/2024 LF : V7.00.00 - Switch to weak linked modules + * + * 08/09/2024 LF : V8.00.00 - Add LCD module */ /* Version exposed to application (including Lua side) */ -#define SELENE_VERSION 7.0010 /* major, minor, sub */ +#define SELENE_VERSION 8.0000 /* major, minor, sub */ From 7630b161a29da2f1509a03d4e4bcb325df06bd72 Mon Sep 17 00:00:00 2001 From: destroyedlolo Date: Sun, 8 Sep 2024 16:30:52 +0200 Subject: [PATCH 04/19] Add shutdown() --- src/SelPlugins/LCD/SelLCD.c | 13 +++++++++++++ src/include/Selene/SelPlug-in/SelLCD.h | 1 + 2 files changed, 14 insertions(+) diff --git a/src/SelPlugins/LCD/SelLCD.c b/src/SelPlugins/LCD/SelLCD.c index 6b7af70..5aa71ba 100644 --- a/src/SelPlugins/LCD/SelLCD.c +++ b/src/SelPlugins/LCD/SelLCD.c @@ -123,6 +123,18 @@ static bool lcdc_Init(struct LCDscreen *lcd, uint16_t bus_number, uint8_t addres return true; } +static void lcdc_Shutdown(struct LCDscreen *lcd){ +/** + * @brief Turn off the screen + * + * @function Shutdown + * @param screen point to the screen handle + */ + selLCD.DisplayCtl(lcd, false, false, false); + close(lcd->bus); + lcd->bus = -1; +} + static void lcdc_DisplayCtl(struct LCDscreen *lcd, bool screen, bool cursor, bool blink){ /** * @brief Display control @@ -196,6 +208,7 @@ bool InitModule( void ){ /* Callbacks */ selLCD.Init = lcdc_Init; + selLCD.Shutdown = lcdc_Shutdown; selLCD.SendCmd = lcdc_SendCmd; selLCD.SendData = lcdc_SendData; selLCD.DisplayCtl = lcdc_DisplayCtl; diff --git a/src/include/Selene/SelPlug-in/SelLCD.h b/src/include/Selene/SelPlug-in/SelLCD.h index a57f8e0..8061a0c 100644 --- a/src/include/Selene/SelPlug-in/SelLCD.h +++ b/src/include/Selene/SelPlug-in/SelLCD.h @@ -30,6 +30,7 @@ struct SelLCD { /* Call backs */ bool (*Init)(struct LCDscreen *, uint16_t bus_number, uint8_t address, bool twolines, bool y11); + void (*Shutdown)(struct LCDscreen *); void (*SendCmd)(struct LCDscreen *, uint8_t); void (*SendData)(struct LCDscreen *, uint8_t); From d7682b06519009c99f3ead7070b2b46350eb0dcd Mon Sep 17 00:00:00 2001 From: destroyedlolo Date: Sun, 8 Sep 2024 16:41:08 +0200 Subject: [PATCH 05/19] Expose SendQuarter --- src/SelPlugins/LCD/SelLCD.c | 16 +++++++++++----- src/include/Selene/SelPlug-in/SelLCD.h | 2 ++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/SelPlugins/LCD/SelLCD.c b/src/SelPlugins/LCD/SelLCD.c index 5aa71ba..2881f9c 100644 --- a/src/SelPlugins/LCD/SelLCD.c +++ b/src/SelPlugins/LCD/SelLCD.c @@ -37,7 +37,7 @@ static struct SelLua *selLua; #define ENABLE 0x04 #define BACKLIGHT 0x08 -static void SendQuarter(struct LCDscreen *lcd, uint8_t b){ +static void lcdc_SendQuarter(struct LCDscreen *lcd, uint8_t b){ /* Send the provided quarter */ write(lcd->bus, &b, 1); /* Present the data on the gpio */ @@ -64,11 +64,11 @@ static void lcdc_SendCmd(struct LCDscreen *lcd, uint8_t dt){ /* Most significant quarter first */ t |= dt & 0xf0; - SendQuarter(lcd, t); + selLCD.SendQuarter(lcd, t); t &= 0x0f; /* Keep only control bits */ t |= dt << 4; /* send less significant quarter */ - SendQuarter(lcd, t); + selLCD.SendQuarter(lcd, t); } static void lcdc_SendData(struct LCDscreen *lcd, uint8_t dt){ @@ -83,11 +83,11 @@ static void lcdc_SendData(struct LCDscreen *lcd, uint8_t dt){ /* Most significant quarter first */ t |= dt & 0xf0; - SendQuarter(lcd, t); + selLCD.SendQuarter(lcd, t); t &= 0x0f; /* Keep only control bits */ t |= dt << 4; /* send less significant quarter */ - SendQuarter(lcd, t); + selLCD.SendQuarter(lcd, t); } static bool lcdc_Init(struct LCDscreen *lcd, uint16_t bus_number, uint8_t address, bool twolines, bool y11){ @@ -207,6 +207,12 @@ bool InitModule( void ){ selLua->AddStartupFunc(registerSelLCD); /* Callbacks */ + + /* This low level can be overwritten for example to use 1-Wire instead + * of I2C + */ + selLCD.SendQuarter = lcdc_SendQuarter; + selLCD.Init = lcdc_Init; selLCD.Shutdown = lcdc_Shutdown; selLCD.SendCmd = lcdc_SendCmd; diff --git a/src/include/Selene/SelPlug-in/SelLCD.h b/src/include/Selene/SelPlug-in/SelLCD.h index 8061a0c..faf0fac 100644 --- a/src/include/Selene/SelPlug-in/SelLCD.h +++ b/src/include/Selene/SelPlug-in/SelLCD.h @@ -29,6 +29,8 @@ struct SelLCD { useconds_t clock_process; /* time to process */ /* Call backs */ + void (*SendQuarter)(struct LCDscreen *, uint8_t); + bool (*Init)(struct LCDscreen *, uint16_t bus_number, uint8_t address, bool twolines, bool y11); void (*Shutdown)(struct LCDscreen *); From 8d4b72f6e4525206c62997da3673fad3d406731d Mon Sep 17 00:00:00 2001 From: destroyedlolo Date: Sun, 8 Sep 2024 17:28:45 +0200 Subject: [PATCH 06/19] Set cursor position --- src/SelPlugins/LCD/SelLCD.c | 60 +++++++++++++++++++++++++- src/include/Selene/SelPlug-in/SelLCD.h | 4 ++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/src/SelPlugins/LCD/SelLCD.c b/src/SelPlugins/LCD/SelLCD.c index 2881f9c..32681e2 100644 --- a/src/SelPlugins/LCD/SelLCD.c +++ b/src/SelPlugins/LCD/SelLCD.c @@ -158,17 +158,71 @@ static void lcdc_EntryCtl(struct LCDscreen *lcd, bool inc, bool shift){ * @brief Entry control * * @function EntryCtl + * * @param screen point to the screen handle * @tparam boolean increment the cursor when a character is sent * @tparam boolean shift the screen if the cursor leaves it */ - uint8_t t = 0x04; /* Enty control */ + uint8_t t = 0x04; /* Entry control */ t |= inc ? 0x02 : 0x00; t |= shift ? 0x01 : 0x00; selLCD.SendCmd(lcd, t); } +static void lcdc_Clear(struct LCDscreen *lcd){ +/** + * @brief Clear the screen + * + * @function Clear + * + * @param screen point to the screen handle + */ + selLCD.SendCmd(lcd, 0x01); +} + +static void lcdc_Home(struct LCDscreen *lcd){ +/** + * @brief Places cursor at up-left position + * + * @function Home + * + * @param screen point to the screen handle + */ + selLCD.SendCmd(lcd, 0x02); +} + +static void lcdc_SetDDRAM(struct LCDscreen *lcd, uint8_t pos){ +/** + * @brief Set display ram pointer + * + * @function SetDDRAM + * + * @param screen point to the screen handle + * @param uint8_t position (<80 otherwise reset to 0) + */ + if(pos > 79) + pos = 0; + + selLCD.SendCmd(lcd, 0x80 | pos); +} + +static void lcdc_SetCursor(struct LCDscreen *lcd, uint8_t x, uint8_t y){ +/** + * @brief set the cursor at x,y position + * + * @function SetCursor + * + * @param screen point to the screen handle + * @param uint8_t x position + * @param uint8_t y position + * + * Notez-bien : there is no boundary check. Up to the developer to know what + * it is doing. + */ + selLCD.SetDDRAM(lcd, y*0x40 + x); +} + static const struct luaL_Reg LCDLib[] = { {NULL, NULL} /* End of definition */ }; @@ -219,6 +273,10 @@ bool InitModule( void ){ selLCD.SendData = lcdc_SendData; selLCD.DisplayCtl = lcdc_DisplayCtl; selLCD.EntryCtl = lcdc_EntryCtl; + selLCD.Clear = lcdc_Clear; + selLCD.Home = lcdc_Home; + selLCD.SetDDRAM = lcdc_SetDDRAM; + selLCD.SetCursor = lcdc_SetCursor; return true; } diff --git a/src/include/Selene/SelPlug-in/SelLCD.h b/src/include/Selene/SelPlug-in/SelLCD.h index faf0fac..a7184f4 100644 --- a/src/include/Selene/SelPlug-in/SelLCD.h +++ b/src/include/Selene/SelPlug-in/SelLCD.h @@ -39,6 +39,10 @@ struct SelLCD { void (*DisplayCtl)(struct LCDscreen *, bool screen, bool cursor, bool blink); void (*EntryCtl)(struct LCDscreen *, bool inc, bool shift); + void (*Clear)(struct LCDscreen *); + void (*Home)(struct LCDscreen *); + void (*SetDDRAM)(struct LCDscreen *, uint8_t); + void (*SetCursor)(struct LCDscreen *, uint8_t, uint8_t); }; #endif From e058ba1b53ef67733d0d9211132855dc8ebed477 Mon Sep 17 00:00:00 2001 From: destroyedlolo Date: Sun, 8 Sep 2024 17:34:19 +0200 Subject: [PATCH 07/19] Add WriteString --- src/SelPlugins/LCD/SelLCD.c | 19 ++++++++++++++++++- src/include/Selene/SelPlug-in/SelLCD.h | 1 + 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/SelPlugins/LCD/SelLCD.c b/src/SelPlugins/LCD/SelLCD.c index 32681e2..85e96e3 100644 --- a/src/SelPlugins/LCD/SelLCD.c +++ b/src/SelPlugins/LCD/SelLCD.c @@ -199,7 +199,7 @@ static void lcdc_SetDDRAM(struct LCDscreen *lcd, uint8_t pos){ * @function SetDDRAM * * @param screen point to the screen handle - * @param uint8_t position (<80 otherwise reset to 0) + * @tparam uint8_t position (<80 otherwise reset to 0) */ if(pos > 79) pos = 0; @@ -207,6 +207,22 @@ static void lcdc_SetDDRAM(struct LCDscreen *lcd, uint8_t pos){ selLCD.SendCmd(lcd, 0x80 | pos); } +static void lcdc_WriteString(struct LCDscreen *lcd, const char *txt){ +/** + * @brief Write a characters string to the screen. + * + * @function WriteString + * + * @param screen point to the screen handle + * @param string to be displayed + * + * Notez-bien : there is no limits, up to the programmer to know + * what it's doing. + */ + for(;*txt; txt++) + selLCD.SendData(lcd, *txt); +} + static void lcdc_SetCursor(struct LCDscreen *lcd, uint8_t x, uint8_t y){ /** * @brief set the cursor at x,y position @@ -277,6 +293,7 @@ bool InitModule( void ){ selLCD.Home = lcdc_Home; selLCD.SetDDRAM = lcdc_SetDDRAM; selLCD.SetCursor = lcdc_SetCursor; + selLCD.WriteString = lcdc_WriteString; return true; } diff --git a/src/include/Selene/SelPlug-in/SelLCD.h b/src/include/Selene/SelPlug-in/SelLCD.h index a7184f4..886e42d 100644 --- a/src/include/Selene/SelPlug-in/SelLCD.h +++ b/src/include/Selene/SelPlug-in/SelLCD.h @@ -43,6 +43,7 @@ struct SelLCD { void (*Home)(struct LCDscreen *); void (*SetDDRAM)(struct LCDscreen *, uint8_t); void (*SetCursor)(struct LCDscreen *, uint8_t, uint8_t); + void (*WriteString)(struct LCDscreen *, const char *); }; #endif From d055e2ec9f4e2acb08fda6bb2f08a5e2932e95f4 Mon Sep 17 00:00:00 2001 From: destroyedlolo Date: Sun, 8 Sep 2024 17:39:09 +0200 Subject: [PATCH 08/19] Set default timing --- src/SelPlugins/LCD/SelLCD.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/SelPlugins/LCD/SelLCD.c b/src/SelPlugins/LCD/SelLCD.c index 85e96e3..f0ad837 100644 --- a/src/SelPlugins/LCD/SelLCD.c +++ b/src/SelPlugins/LCD/SelLCD.c @@ -276,13 +276,18 @@ bool InitModule( void ){ registerSelLCD(NULL); selLua->AddStartupFunc(registerSelLCD); - /* Callbacks */ + /* Default timings */ + + selLCD.clock_pulse = 500; + selLCD.clock_process = 4100; /* This low level can be overwritten for example to use 1-Wire instead * of I2C */ selLCD.SendQuarter = lcdc_SendQuarter; + /* Callbacks */ + selLCD.Init = lcdc_Init; selLCD.Shutdown = lcdc_Shutdown; selLCD.SendCmd = lcdc_SendCmd; From cfacb5865f892cd801c3666a31ef108c978b0fe2 Mon Sep 17 00:00:00 2001 From: destroyedlolo Date: Sun, 8 Sep 2024 18:00:44 +0200 Subject: [PATCH 09/19] No Lua needed for C example --- remake.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/remake.sh b/remake.sh index 2cbc15c..b8ac700 100644 --- a/remake.sh +++ b/remake.sh @@ -523,7 +523,7 @@ rm -f make.sh for f in *.c do - echo "cc -I../src/include/ \$( pkg-config --cflags lua$VERLUA ) $CFLAGS $DEBUG $MCHECK $MCHECK_LIB $USE_PLUGDIR -L../lib -l:libSelene.so.2 -lpaho-mqtt3c -lm -ldl -Wl,--export-dynamic -lpthread $f -o $( basename $f .c )" >> make.sh + echo "cc -I../src/include/ $CFLAGS $DEBUG $MCHECK $MCHECK_LIB $USE_PLUGDIR -L../lib -l:libSelene.so.2 -lpaho-mqtt3c -lm -ldl -Wl,--export-dynamic -lpthread $f -o $( basename $f .c )" >> make.sh done cd ../.. From 8659fba00b65e78d732587505cd0a0956a4ae6b3 Mon Sep 17 00:00:00 2001 From: destroyedlolo Date: Sun, 8 Sep 2024 18:11:35 +0200 Subject: [PATCH 10/19] Lua is optional --- src/SelPlugins/LCD/SelLCD.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/SelPlugins/LCD/SelLCD.c b/src/SelPlugins/LCD/SelLCD.c index f0ad837..9db15c9 100644 --- a/src/SelPlugins/LCD/SelLCD.c +++ b/src/SelPlugins/LCD/SelLCD.c @@ -273,8 +273,14 @@ bool InitModule( void ){ registerModule((struct SelModule *)&selLCD); - registerSelLCD(NULL); - selLua->AddStartupFunc(registerSelLCD); + if(selLua){ /* Only if Lua is used */ + registerSelLCD(NULL); + selLua->AddStartupFunc(registerSelLCD); + } +#ifdef DEBUG + else + selLog->Log('D', "SelLua not loaded"); +#endif /* Default timings */ From 26eed63130b68210416c6dee01437f366d8ea53b Mon Sep 17 00:00:00 2001 From: destroyedlolo Date: Sun, 8 Sep 2024 18:18:48 +0200 Subject: [PATCH 11/19] Add backlight() --- src/SelPlugins/LCD/SelLCD.c | 12 ++++++++++++ src/include/Selene/SelPlug-in/SelLCD.h | 1 + 2 files changed, 13 insertions(+) diff --git a/src/SelPlugins/LCD/SelLCD.c b/src/SelPlugins/LCD/SelLCD.c index 9db15c9..3c2cc2d 100644 --- a/src/SelPlugins/LCD/SelLCD.c +++ b/src/SelPlugins/LCD/SelLCD.c @@ -135,6 +135,17 @@ static void lcdc_Shutdown(struct LCDscreen *lcd){ lcd->bus = -1; } +static void lcdc_backlight(struct LCDscreen *lcd, bool bl){ +/** + * @brief Turn backlight on or off (for next command) + * + * @function backlight + * @param screen point to the screen handle + * @tparam boolean status of the backlight + */ + lcd->backlight = bl; +} + static void lcdc_DisplayCtl(struct LCDscreen *lcd, bool screen, bool cursor, bool blink){ /** * @brief Display control @@ -298,6 +309,7 @@ bool InitModule( void ){ selLCD.Shutdown = lcdc_Shutdown; selLCD.SendCmd = lcdc_SendCmd; selLCD.SendData = lcdc_SendData; + selLCD.backlight = lcdc_backlight; selLCD.DisplayCtl = lcdc_DisplayCtl; selLCD.EntryCtl = lcdc_EntryCtl; selLCD.Clear = lcdc_Clear; diff --git a/src/include/Selene/SelPlug-in/SelLCD.h b/src/include/Selene/SelPlug-in/SelLCD.h index 886e42d..f834394 100644 --- a/src/include/Selene/SelPlug-in/SelLCD.h +++ b/src/include/Selene/SelPlug-in/SelLCD.h @@ -37,6 +37,7 @@ struct SelLCD { void (*SendCmd)(struct LCDscreen *, uint8_t); void (*SendData)(struct LCDscreen *, uint8_t); + void (*backlight)(struct LCDscreen *, bool); void (*DisplayCtl)(struct LCDscreen *, bool screen, bool cursor, bool blink); void (*EntryCtl)(struct LCDscreen *, bool inc, bool shift); void (*Clear)(struct LCDscreen *); From 7bae3ec52a620d039f2fb43fd2d4874e113b8e93 Mon Sep 17 00:00:00 2001 From: destroyedlolo Date: Sun, 8 Sep 2024 19:34:43 +0200 Subject: [PATCH 12/19] Cosmetic --- src/SelPlugins/LCD/SelLCD.c | 4 ++-- src/include/Selene/SelPlug-in/SelLCD.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/SelPlugins/LCD/SelLCD.c b/src/SelPlugins/LCD/SelLCD.c index 3c2cc2d..6c836e5 100644 --- a/src/SelPlugins/LCD/SelLCD.c +++ b/src/SelPlugins/LCD/SelLCD.c @@ -135,7 +135,7 @@ static void lcdc_Shutdown(struct LCDscreen *lcd){ lcd->bus = -1; } -static void lcdc_backlight(struct LCDscreen *lcd, bool bl){ +static void lcdc_Backlight(struct LCDscreen *lcd, bool bl){ /** * @brief Turn backlight on or off (for next command) * @@ -309,7 +309,7 @@ bool InitModule( void ){ selLCD.Shutdown = lcdc_Shutdown; selLCD.SendCmd = lcdc_SendCmd; selLCD.SendData = lcdc_SendData; - selLCD.backlight = lcdc_backlight; + selLCD.Backlight = lcdc_Backlight; selLCD.DisplayCtl = lcdc_DisplayCtl; selLCD.EntryCtl = lcdc_EntryCtl; selLCD.Clear = lcdc_Clear; diff --git a/src/include/Selene/SelPlug-in/SelLCD.h b/src/include/Selene/SelPlug-in/SelLCD.h index f834394..3b51e31 100644 --- a/src/include/Selene/SelPlug-in/SelLCD.h +++ b/src/include/Selene/SelPlug-in/SelLCD.h @@ -37,7 +37,7 @@ struct SelLCD { void (*SendCmd)(struct LCDscreen *, uint8_t); void (*SendData)(struct LCDscreen *, uint8_t); - void (*backlight)(struct LCDscreen *, bool); + void (*Backlight)(struct LCDscreen *, bool); void (*DisplayCtl)(struct LCDscreen *, bool screen, bool cursor, bool blink); void (*EntryCtl)(struct LCDscreen *, bool inc, bool shift); void (*Clear)(struct LCDscreen *); From 440c65d4463c434d92d5a24b24d25341eea88897 Mon Sep 17 00:00:00 2001 From: destroyedlolo Date: Sun, 8 Sep 2024 19:35:50 +0200 Subject: [PATCH 13/19] Add LED C example --- Clenites/LCD.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 Clenites/LCD.c diff --git a/Clenites/LCD.c b/Clenites/LCD.c new file mode 100644 index 0000000..5770549 --- /dev/null +++ b/Clenites/LCD.c @@ -0,0 +1,134 @@ +/* Demonstration of Séléné LCD module. + * Display all native characters + * + * 08/09/2024 - First version + */ + +/* Basic modules needed by almost all applications */ +#include /* Modules : the only part hardly linked */ +#include /* Selene's core functionalities */ +#include /* Logging : not really mandatory but very useful in most of the cases */ + +#include + + /* Here start 'standard' C code */ +#include /* dlerror(), ... */ +#include /* exit(), ... */ +#include + +int main( int ac, char ** av){ + uint16_t verfound; + + /* Load core functionalities */ + struct SeleneCore *SeleneCore = (struct SeleneCore *)loadModule("SeleneCore", SELENECORE_VERSION, &verfound); +#ifdef DEBUG + printf("*D* SeleneCore %s : version %u\n", SeleneCore ? "found":"not found", verfound); +#endif + if(!SeleneCore){ /* Needs to do checks manually as SeleneCore is ... not loaded */ + printf("*F* : can't load SeleneCore "); + if(verfound) + printf("(%u instead of expected %u)\n", verfound, SELENECORE_VERSION); + else { + char *err = dlerror(); + if(!err) + puts(" : missing InitModule() or newer SelModule expected"); + else + printf("(%s)\n", dlerror()); + } + + exit(EXIT_FAILURE); + } + + struct SelLog *SelLog = (struct SelLog *)SeleneCore->loadModule("SelLog", SELLOG_VERSION, &verfound, 'F'); + + /* We still need to do it manually as SeleneCore->loadModule() still can't logging */ + if(!SelLog){ + printf("*F* : can't load SelLog "); + if(verfound) + printf("(%u instead of expected %u)\n", verfound, SELLOG_VERSION); + else { + char *err = dlerror(); + if(!err) + puts(" : missing InitModule() or outdated dependency found"); + else + printf("(%s)\n", dlerror()); + } + + exit(EXIT_FAILURE); + } + + /* *** + * Here your application code + * ***/ + + /* Load SelLCD module ... using SeleneCore's facilities as logging is enabled */ + struct SelLCD *SelLCD = (struct SelLCD *)SeleneCore->loadModule("SelLCD", SELLCD_VERSION, &verfound, 'F'); + if(!SelLCD) + exit(EXIT_FAILURE); + + /* LCD own code starting here */ + uint16_t nbus = 2; /* BananaPI bus by default */ + uint8_t addr = 0x27; /* screen address */ + bool verbose = false; + + int c; + while((c = getopt(ac, av, "hvb:a:")) != EOF) switch(c){ + case 'b': + nbus = atoi(optarg); + break; + case 'a': + addr = atoi(optarg); + break; + case 'v': + verbose = true; + break; + case 'h': + default : + printf("Known options :\n" + "\t-b : i2c bus number (default 2)\n" + "\t-a ! device's address (default 0x27)\n" + "\t-v : be verbose\n" + ); + exit( c == 'h' ? EXIT_SUCCESS : EXIT_FAILURE); + } + + if(verbose) + printf("Targeting slave 0x%02x on /dev/i2c-%d\n", addr, nbus); + + struct LCDscreen lcd; + + if(!SelLCD->Init(&lcd, nbus, addr, true, false)) /* 16x02 screen */ + exit(EXIT_FAILURE); + + SelLCD->Clear(&lcd); + SelLCD->WriteString(&lcd, "Hello"); + SelLCD->Backlight(&lcd, true); /* Backlight on */ + SelLCD->DisplayCtl(&lcd, true, true, true); /* On, cursor blinking */ + getchar(); + + SelLCD->DisplayCtl(&lcd, true, false, true); /* Only the block blinking */ + for(uint16_t i = 0x00; i < 0x100; i += 0x10){ + char t[6]; + sprintf(t, "0x%02x", i); + + /* Write the characters' group */ + SelLCD->Clear(&lcd); + SelLCD->WriteString(&lcd, t); + + SelLCD->SetCursor(&lcd, 0,1); /* 2nd lines */ + t[1] = 0; + + for(uint8_t j = 0x00; j < 0x10; j++){ + *t = i+j; + SelLCD->WriteString(&lcd, t); + } + + SelLCD->SetCursor(&lcd, 15,0); /* Display the cursor on the top right */ + getchar(); + } + + /* The end */ + SelLCD->Backlight(&lcd, false); + SelLCD->Shutdown(&lcd); +} + From 813b223bfb019eea6eaf5c2317bb5a09a4df0890 Mon Sep 17 00:00:00 2001 From: destroyedlolo Date: Sun, 8 Sep 2024 20:12:16 +0200 Subject: [PATCH 14/19] Init() --- src/SelPlugins/LCD/SelLCD.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/SelPlugins/LCD/SelLCD.c b/src/SelPlugins/LCD/SelLCD.c index 6c836e5..786a63d 100644 --- a/src/SelPlugins/LCD/SelLCD.c +++ b/src/SelPlugins/LCD/SelLCD.c @@ -16,6 +16,7 @@ #include #include #include +#include static struct SelLCD selLCD; @@ -123,6 +124,23 @@ static bool lcdc_Init(struct LCDscreen *lcd, uint16_t bus_number, uint8_t addres return true; } +static int lcdl_Init(lua_State *L){ + uint16_t nbus = luaL_checkinteger(L, 1); + uint8_t addr = luaL_checkinteger(L, 2); + bool twolines = lua_toboolean(L, 3); + bool y11 = lua_toboolean(L, 4); + + struct LCDscreen *lcd = (struct LCDscreen *)lua_newuserdata(L, sizeof(struct LCDscreen)); + assert(lcd); + + luaL_getmetatable(L, "SelLCD"); + lua_setmetatable(L, -2); + + selLCD.Init(lcd, nbus, addr, twolines, y11); + + return 1; +} + static void lcdc_Shutdown(struct LCDscreen *lcd){ /** * @brief Turn off the screen @@ -250,12 +268,19 @@ static void lcdc_SetCursor(struct LCDscreen *lcd, uint8_t x, uint8_t y){ selLCD.SetDDRAM(lcd, y*0x40 + x); } +static const struct luaL_Reg LCDM[] = { + {NULL, NULL} /* End of definition */ +}; + static const struct luaL_Reg LCDLib[] = { + {"Init", lcdl_Init}, + {"Attach", lcdl_Init}, {NULL, NULL} /* End of definition */ }; static void registerSelLCD(lua_State *L){ selLua->libCreateOrAddFuncs(L, "SelLCD", LCDLib); + selLua->objFuncs(L, "SelLCD", LCDM); } /* *** From ea655210a9cfa2ca7860c973a3e4397927a3377c Mon Sep 17 00:00:00 2001 From: destroyedlolo Date: Sun, 8 Sep 2024 20:26:43 +0200 Subject: [PATCH 15/19] Backlight --- src/SelPlugins/LCD/SelLCD.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/SelPlugins/LCD/SelLCD.c b/src/SelPlugins/LCD/SelLCD.c index 786a63d..7c3df22 100644 --- a/src/SelPlugins/LCD/SelLCD.c +++ b/src/SelPlugins/LCD/SelLCD.c @@ -38,6 +38,13 @@ static struct SelLua *selLua; #define ENABLE 0x04 #define BACKLIGHT 0x08 +static struct LCDscreen *checkSelLCD(lua_State *L){ + void *r = selLua->testudata(L, 1, "SelLCD"); + luaL_argcheck(L, r != NULL, 1, "'SelLCD' expected"); + + return (struct LCDscreen *)r; +} + static void lcdc_SendQuarter(struct LCDscreen *lcd, uint8_t b){ /* Send the provided quarter */ @@ -153,6 +160,14 @@ static void lcdc_Shutdown(struct LCDscreen *lcd){ lcd->bus = -1; } +static int lcdl_Shutdown(lua_State *L){ + struct LCDscreen *lcd = checkSelLCD(L); + + selLCD.Shutdown(lcd); + + return 0; +} + static void lcdc_Backlight(struct LCDscreen *lcd, bool bl){ /** * @brief Turn backlight on or off (for next command) @@ -164,6 +179,15 @@ static void lcdc_Backlight(struct LCDscreen *lcd, bool bl){ lcd->backlight = bl; } +static int lcdl_Backlight(lua_State *L){ + struct LCDscreen *lcd = checkSelLCD(L); + bool bl = lua_toboolean(L, 2); + + selLCD.Backlight(lcd, bl); + + return 0; +} + static void lcdc_DisplayCtl(struct LCDscreen *lcd, bool screen, bool cursor, bool blink){ /** * @brief Display control @@ -269,6 +293,9 @@ static void lcdc_SetCursor(struct LCDscreen *lcd, uint8_t x, uint8_t y){ } static const struct luaL_Reg LCDM[] = { + {"Shutdown", lcdl_Shutdown}, + {"Backlight", lcdl_Backlight}, + {NULL, NULL} /* End of definition */ }; From b675fe0d5ded6e6c09f395694cf5cd4558933267 Mon Sep 17 00:00:00 2001 From: destroyedlolo Date: Sun, 8 Sep 2024 22:08:05 +0200 Subject: [PATCH 16/19] Add some functions --- src/SelPlugins/LCD/SelLCD.c | 41 +++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/SelPlugins/LCD/SelLCD.c b/src/SelPlugins/LCD/SelLCD.c index 7c3df22..0d41acc 100644 --- a/src/SelPlugins/LCD/SelLCD.c +++ b/src/SelPlugins/LCD/SelLCD.c @@ -206,6 +206,17 @@ static void lcdc_DisplayCtl(struct LCDscreen *lcd, bool screen, bool cursor, boo selLCD.SendCmd(lcd, t); } +static int lcdl_DisplayCtl(lua_State *L){ + struct LCDscreen *lcd = checkSelLCD(L); + bool screen = lua_toboolean(L, 2); + bool cursor = lua_toboolean(L, 3); + bool blink = lua_toboolean(L, 4); + + selLCD.DisplayCtl(lcd, screen, cursor, blink); + + return 0; +} + static void lcdc_EntryCtl(struct LCDscreen *lcd, bool inc, bool shift){ /** * @brief Entry control @@ -223,6 +234,16 @@ static void lcdc_EntryCtl(struct LCDscreen *lcd, bool inc, bool shift){ selLCD.SendCmd(lcd, t); } +static int lcdl_EntryCtl(lua_State *L){ + struct LCDscreen *lcd = checkSelLCD(L); + bool inc = lua_toboolean(L, 2); + bool shift = lua_toboolean(L, 3); + + selLCD.EntryCtl(lcd, inc, shift); + + return 0; +} + static void lcdc_Clear(struct LCDscreen *lcd){ /** * @brief Clear the screen @@ -234,6 +255,14 @@ static void lcdc_Clear(struct LCDscreen *lcd){ selLCD.SendCmd(lcd, 0x01); } +static int lcdl_Clear(lua_State *L){ + struct LCDscreen *lcd = checkSelLCD(L); + + selLCD.Clear(lcd); + + return 0; +} + static void lcdc_Home(struct LCDscreen *lcd){ /** * @brief Places cursor at up-left position @@ -245,6 +274,14 @@ static void lcdc_Home(struct LCDscreen *lcd){ selLCD.SendCmd(lcd, 0x02); } +static int lcdl_Home(lua_State *L){ + struct LCDscreen *lcd = checkSelLCD(L); + + selLCD.Home(lcd); + + return 0; +} + static void lcdc_SetDDRAM(struct LCDscreen *lcd, uint8_t pos){ /** * @brief Set display ram pointer @@ -295,6 +332,10 @@ static void lcdc_SetCursor(struct LCDscreen *lcd, uint8_t x, uint8_t y){ static const struct luaL_Reg LCDM[] = { {"Shutdown", lcdl_Shutdown}, {"Backlight", lcdl_Backlight}, + {"DisplayCtl", lcdl_DisplayCtl}, + {"EntryCtl", lcdl_EntryCtl}, + {"Clear", lcdl_Clear}, + {"Home", lcdl_Home}, {NULL, NULL} /* End of definition */ }; From f8115ef21319b657cc28faced3726060f2e9a68e Mon Sep 17 00:00:00 2001 From: destroyedlolo Date: Sun, 8 Sep 2024 22:15:14 +0200 Subject: [PATCH 17/19] Add cursor manipulation --- src/SelPlugins/LCD/SelLCD.c | 50 ++++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/src/SelPlugins/LCD/SelLCD.c b/src/SelPlugins/LCD/SelLCD.c index 0d41acc..e4c4dd3 100644 --- a/src/SelPlugins/LCD/SelLCD.c +++ b/src/SelPlugins/LCD/SelLCD.c @@ -297,20 +297,13 @@ static void lcdc_SetDDRAM(struct LCDscreen *lcd, uint8_t pos){ selLCD.SendCmd(lcd, 0x80 | pos); } -static void lcdc_WriteString(struct LCDscreen *lcd, const char *txt){ -/** - * @brief Write a characters string to the screen. - * - * @function WriteString - * - * @param screen point to the screen handle - * @param string to be displayed - * - * Notez-bien : there is no limits, up to the programmer to know - * what it's doing. - */ - for(;*txt; txt++) - selLCD.SendData(lcd, *txt); +static int lcdl_SetDDRAM(lua_State *L){ + struct LCDscreen *lcd = checkSelLCD(L); + uint8_t pos = lua_toboolean(L, 2); + + selLCD.SetDDRAM(lcd, pos); + + return 0; } static void lcdc_SetCursor(struct LCDscreen *lcd, uint8_t x, uint8_t y){ @@ -329,6 +322,32 @@ static void lcdc_SetCursor(struct LCDscreen *lcd, uint8_t x, uint8_t y){ selLCD.SetDDRAM(lcd, y*0x40 + x); } +static int lcdl_SetCursor(lua_State *L){ + struct LCDscreen *lcd = checkSelLCD(L); + uint8_t x = lua_toboolean(L, 2); + uint8_t y = lua_toboolean(L, 3); + + selLCD.SetCursor(lcd, x,y); + + return 0; +} + +static void lcdc_WriteString(struct LCDscreen *lcd, const char *txt){ +/** + * @brief Write a characters string to the screen. + * + * @function WriteString + * + * @param screen point to the screen handle + * @param string to be displayed + * + * Notez-bien : there is no limits, up to the programmer to know + * what it's doing. + */ + for(;*txt; txt++) + selLCD.SendData(lcd, *txt); +} + static const struct luaL_Reg LCDM[] = { {"Shutdown", lcdl_Shutdown}, {"Backlight", lcdl_Backlight}, @@ -336,7 +355,8 @@ static const struct luaL_Reg LCDM[] = { {"EntryCtl", lcdl_EntryCtl}, {"Clear", lcdl_Clear}, {"Home", lcdl_Home}, - + {"SetDDRAM", lcdl_SetDDRAM}, + {"SetCursor", lcdl_SetCursor}, {NULL, NULL} /* End of definition */ }; From 898ced8f7369baa544c8fd1244c9c045e1429768 Mon Sep 17 00:00:00 2001 From: destroyedlolo Date: Sun, 8 Sep 2024 22:20:58 +0200 Subject: [PATCH 18/19] Add WriteString --- src/SelPlugins/LCD/SelLCD.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/SelPlugins/LCD/SelLCD.c b/src/SelPlugins/LCD/SelLCD.c index e4c4dd3..5473e72 100644 --- a/src/SelPlugins/LCD/SelLCD.c +++ b/src/SelPlugins/LCD/SelLCD.c @@ -348,6 +348,15 @@ static void lcdc_WriteString(struct LCDscreen *lcd, const char *txt){ selLCD.SendData(lcd, *txt); } +static int lcdl_WriteString(lua_State *L){ + struct LCDscreen *lcd = checkSelLCD(L); + const char *s = luaL_checkstring(L, 2); + + selLCD.WriteString(lcd, s); + + return 0; +} + static const struct luaL_Reg LCDM[] = { {"Shutdown", lcdl_Shutdown}, {"Backlight", lcdl_Backlight}, @@ -357,6 +366,7 @@ static const struct luaL_Reg LCDM[] = { {"Home", lcdl_Home}, {"SetDDRAM", lcdl_SetDDRAM}, {"SetCursor", lcdl_SetCursor}, + {"WriteString", lcdl_WriteString}, {NULL, NULL} /* End of definition */ }; From 271d29b5c3b4961816b85f9a5bb169f846332471 Mon Sep 17 00:00:00 2001 From: destroyedlolo Date: Sun, 8 Sep 2024 23:35:09 +0200 Subject: [PATCH 19/19] Add Lua example --- SelenitesLCD/AllChar.sel | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 SelenitesLCD/AllChar.sel diff --git a/SelenitesLCD/AllChar.sel b/SelenitesLCD/AllChar.sel new file mode 100644 index 0000000..787f816 --- /dev/null +++ b/SelenitesLCD/AllChar.sel @@ -0,0 +1,33 @@ +#!./Selene +--- Demonstration of subsurface usage + +Selene.Use("SelLCD") +Selene.LetsGo() -- ensure late building dependencies + + -- Init the screen handle + -- Suitable for my BananaPI +lcd = SelLCD.Init(2, 0x27, true, false) + +lcd:Clear() +lcd:WriteString("Hello") +lcd:Backlight(true) +lcd:DisplayCtl(true, true, true) -- On, cursor blinking +io.stdin:read'*l' -- wait for enter + +lcd:DisplayCtl(true, false, true) -- Only the block blinking + +for i = 0x00, 0xf0, 0x10 do + lcd:Clear() + lcd:WriteString( string.format('0x%02x', i) ) + + lcd:SetCursor(0,1) + for j = 0x00, 0x0f do + lcd:WriteString( string.char(i+j) ) + end + + lcd:SetCursor(15,0) + io.stdin:read'*l' -- wait for enter +end + +lcd:Backlight(false) +lcd:Shutdown()