142 lines
3.3 KiB
JavaScript
142 lines
3.3 KiB
JavaScript
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,
|
|
}
|
|
} },
|
|
})
|