diff --git a/packages/sampleprj/src/maingrovelcd16x2.ts b/packages/sampleprj/src/maingrovelcd16x2.ts new file mode 100644 index 0000000000..4b3b416127 --- /dev/null +++ b/packages/sampleprj/src/maingrovelcd16x2.ts @@ -0,0 +1,172 @@ +import "@dsboard/seeed_xiao_esp32c3" +import * as ds from "@devicescript/core" +import { I2CDriver, XiaoExpansionBoard } from "@devicescript/drivers" +import { delay } from "@devicescript/core" +import { configureHardware } from "@devicescript/servers" + +// Device I2C Arress +const LCD_ADDRESS = 0x7c >> 1 +const RGB_ADDRESS = 0xc4 >> 1 +const RGB_ADDRESS_V5 = 0x30 + +// color define +const WHITE = 0 +const RED = 1 +const GREEN = 2 +const BLUE = 3 + +const REG_MODE1 = 0x00 +const REG_MODE2 = 0x01 +const REG_OUTPUT = 0x08 + +// commands +const LCD_CLEARDISPLAY = 0x01 +const LCD_RETURNHOME = 0x02 +const LCD_ENTRYMODESET = 0x04 +const LCD_DISPLAYCONTROL = 0x08 +const LCD_CURSORSHIFT = 0x10 +const LCD_FUNCTIONSET = 0x20 +const LCD_SETCGRAMADDR = 0x40 +const LCD_SETDDRAMADDR = 0x80 + +// flags for display entry mode +const LCD_ENTRYRIGHT = 0x00 +const LCD_ENTRYLEFT = 0x02 +const LCD_ENTRYSHIFTINCREMENT = 0x01 +const LCD_ENTRYSHIFTDECREMENT = 0x00 + +// flags for display on/off control +const LCD_DISPLAYON = 0x04 +const LCD_DISPLAYOFF = 0x00 +const LCD_CURSORON = 0x02 +const LCD_CURSOROFF = 0x00 +const LCD_BLINKON = 0x01 +const LCD_BLINKOFF = 0x00 + +// flags for display/cursor shift +const LCD_DISPLAYMOVE = 0x08 +const LCD_CURSORMOVE = 0x00 +const LCD_MOVERIGHT = 0x04 +const LCD_MOVELEFT = 0x00 + +// flags for function set +const LCD_8BITMODE = 0x10 +const LCD_4BITMODE = 0x00 +const LCD_2LINE = 0x08 +const LCD_1LINE = 0x00 +const LCD_5x10DOTS = 0x04 +const LCD_5x8DOTS = 0x00 + +// https://wiki.seeedstudio.com/Grove-16x2_LCD_Series/#specification +// converted from https://github.com/Seeed-Studio/Grove_LCD_RGB_Backlight/ +class RGBLCD extends I2CDriver { + readonly columns: number + readonly lines: number + readonly dotsize: number + private _displayfunction: number = 0 + private _displaymode: number = 0 + private _displaycontrol: number = 0 + private _currline: number = 0 + + constructor( + readonly options: { + columns: number + rows: number + dotsize: number + devAddr?: number + } + ) { + super(options.devAddr || LCD_ADDRESS) + this.columns = options.columns + this.lines = options.rows + this.dotsize = options.dotsize + } + + async initDriver(): Promise { + if (this.lines > 1) { + this._displayfunction |= LCD_2LINE + } + this._currline = 0 + + // for some 1 line displays you can select a 10 pixel high font + if (this.dotsize !== 0 && this.lines === 1) { + this._displayfunction |= LCD_5x10DOTS + } + + // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION! + // according to datasheet, we need at least 40ms after power rises above 2.7V + // before sending commands. Arduino can turn on way befer 4.5V so we'll wait 50 + // delayMicroseconds(50000); + await delay(5) + + // this is according to the hitachi HD44780 datasheet + // page 45 figure 23 + + // Send function set command sequence + await this.command(LCD_FUNCTIONSET | this._displayfunction) + await delay(5) // wait more than 4.1ms + + // second try + await this.command(LCD_FUNCTIONSET | this._displayfunction) + await delay(1) + + // third go + await this.command(LCD_FUNCTIONSET | this._displayfunction) + + // finally, set # lines, font size, etc. + await this.command(LCD_FUNCTIONSET | this._displayfunction) + + // turn the display on with no cursor or blinking default + this._displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF + await this.display() + + // clear it off + await this.clear() + + // Initialize to default text direction (for romance languages) + this._displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT + // set the entry mode + await this.command(LCD_ENTRYMODESET | this._displaymode) + } + + private async command(value: number): Promise { + await this.writeBuf(Buffer.from([0x80, value])) + } + + private async display() { + this._displaycontrol |= LCD_DISPLAYON + await this.command(LCD_DISPLAYCONTROL | this._displaycontrol) + } + + async clear() { + await this.command(LCD_CLEARDISPLAY) // clear display, set cursor position to zero + await delay(2) // this command takes a long time! + } + + private async write(value: number) { + await this.writeBuf(Buffer.from([0x40, value])) + } + + async print(str: string) { + for (let i = 0; i < str.length; ++i) { + await this.write(str.charCodeAt(i)) + } + } +} + +const board = new XiaoExpansionBoard() + +console.log("start...") +const lcd = new RGBLCD({ + columns: 16, + rows: 2, + dotsize: 0, + devAddr: LCD_ADDRESS, +}) +await lcd.init() +setInterval(async () => { + const t = ds.millis() + "" + console.log(t) + await lcd.clear() + await lcd.print(t) +}, 1000)