import i2c from 'i2c-bus'; function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)) } const ROW_OFFSET = [0x00, 0x40, 0x14, 0x54] export class LCD { font_size = 8 lines = 2 backlight = true #device #addr #bus constructor (device, addr) { this.#device = device this.#addr = addr } async open() { this.#bus = await i2c.openPromisified(this.#device) for (let i = 0; i < 3; i++) { await this.sendByte(0x30) await sleep(1) } await this.sendByte(0x20) await sleep(1) await this.send(LCD.FunctionSet(4, this.lines, this.font_size)) await this.send(LCD.DisplayOnOff(true, false, false)) await this.send(LCD.EntryModeSet('right', false)) await this.send(LCD.ClearDisplay()) } async sendString(str) { for (let i = 0; i < str.length; i++) { await this.send(LCD.WriteData(str.charCodeAt(i))) } } async jump(col, row) { col %= 20 row = ROW_OFFSET[row % 4] await this.send(LCD.SetDDRamAddr(row | col)) } async close() { await this.#bus.close() } //RS RW D7 D6 D5 D4 D3 D2 D1 D0 //D7 D6 D5 D4 BL EN RW RS async send(instruction) { const RS = (instruction.value & 0x200) >>> 9 const BL = (this.backlight ? 1 : 0) << 3 const RW = (instruction.value & 0x100) >>> 7 const D74 = (instruction.value & 0x0F0) const D30 = (instruction.value & 0x00F) << 4 await this.sendByte(D74 | BL | RS | RW) await this.sendByte(D30 | BL | RS | RW) await sleep(instruction.delay) } async sendByte(byte) { await this.writeByte(byte) await this.writeByte(byte | 4) await this.writeByte(byte) } async writeByte(byte) { await this.#bus.i2cWrite(this.#addr, 1, Buffer.from([byte])) } } Object.defineProperties(LCD, { ClearDisplay: { value: function() { return { value: 0x1, delay: 2, } } }, EntryModeSet: { value: function(direction, display_shift) { const I_Direction = (direction == 'right' ? 1 : 0) << 1 const Shift = (display_shift ? 1 : 0) return { value: 0x4 | I_Direction | Shift, delay: 1, } } }, DisplayOnOff: { value: function(display, cursor, cursor_position) { const Display = (display ? 1 : 0) << 2 const Cursor = (cursor ? 1 : 0) << 1 const Cursor_Position = (cursor_position ? 1 : 0) return { value: 0x8 | Display | Cursor | Cursor_Position, delay: 1, } } }, CursorDisplayShift: { value: function(target, direction) { const Screen_Cursor = (target == 'display' ? 1 : 0) << 3 const Right_Left = (direction == 'right' ? 1 : 0) << 2 return { value: 0x10 | Screen_Cursor | Right_Left, delay: 1, } } }, FunctionSet: { value: function(data_length, number_of_lines, font_size) { const Data_Length = (data_length == 8 ? 1 : 0) << 4 const Number_of_lines = (number_of_lines == 2 ? 1 : 0) << 3 const Font_size = (font_size == 11 ? 1 : 0) << 2 return { value: 0x20 | Data_Length | Number_of_lines | Font_size, delay: 1, } } }, SetDDRamAddr: { value: function(address) { address &= 0x7F return { value: 0x80 | address, delay: 1, } } }, WriteData: { value: function(byte) { byte &= 0xFF return { value: 0x200 | byte, delay: 1, } } }, })