Skip to content

Commit

Permalink
fix: avoid drawing lcd dead zones
Browse files Browse the repository at this point in the history
  • Loading branch information
Julusian committed Apr 17, 2023
1 parent 1e6c693 commit a133410
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 13 deletions.
21 changes: 14 additions & 7 deletions packages/core/src/models/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
RGBColor,
} from '../constants'
import { LoupedeckSerialConnection } from '../serial'
import { checkRGBColor, checkRGBValue, encodeBuffer } from '../util'
import { checkRGBColor, checkRGBValue, createCanDrawPixel, encodeBuffer } from '../util'
import { LoupedeckControlDefinition, LoupedeckDevice } from './interface'
import { LoupedeckModelId } from '../info'
import PQueue from 'p-queue'
Expand Down Expand Up @@ -163,8 +163,6 @@ export abstract class LoupedeckDeviceBase extends EventEmitter<LoupedeckDeviceEv
): [buffer: Buffer, offset: number] {
const padding = 10 // header + id

console.log('drawing', x, y)

const pixelCount = width * height
const encoded = Buffer.alloc(pixelCount * 2 + padding)

Expand Down Expand Up @@ -198,8 +196,8 @@ export abstract class LoupedeckDeviceBase extends EventEmitter<LoupedeckDeviceEv

const [encoded, padding] = this.createBufferWithHeader(display, width, height, x + display.xPadding, y)

// TODO - blank dead zones in encoded buffer
encodeBuffer(buffer, encoded, format, padding, width * height)
const [canDrawPixel, canDrawRow] = createCanDrawPixel(x, y, this.lcdKeySize, display)
encodeBuffer(buffer, encoded, format, padding, width, height, canDrawPixel, canDrawRow)

await this.#runInQueueIfEnabled(async () => {
// Run in the queue as a single operation
Expand Down Expand Up @@ -242,9 +240,18 @@ export abstract class LoupedeckDeviceBase extends EventEmitter<LoupedeckDeviceEv
((Math.round(color.green) & 0b111111) << 5) +
(Math.round(color.blue) & 0b11111)

const [canDrawPixel, canDrawRow] = createCanDrawPixel(x, y, this.lcdKeySize, display)

const [encoded, padding] = this.createBufferWithHeader(display, width, height, x + display.xPadding, y)
for (let i = 0; i < width * height; i++) {
encoded.writeUint16LE(encodedValue, i * 2 + padding)
for (let y = 0; y < height; y++) {
if (!canDrawRow(y)) continue

for (let x = 0; x < width; x++) {
if (canDrawPixel(x, y)) {
const i = y * width + x
encoded.writeUint16LE(encodedValue, i * 2 + padding)
}
}
}

await this.#runInQueueIfEnabled(async () => {
Expand Down
61 changes: 55 additions & 6 deletions packages/core/src/util.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,73 @@
import { LoupedeckBufferFormat, RGBColor } from './constants'
import { LoupedeckDisplayDefinition } from './models/base'

export type CanDrawPixelFn = (x: number, y: number) => boolean
export type CanDrawRowFn = (y: number) => boolean

export function createCanDrawPixel(
drawX: number,
drawY: number,
lcdKeySize: number,
displayInfo: Pick<LoupedeckDisplayDefinition, 'rowGap' | 'columnGap'>
): [CanDrawPixelFn, CanDrawRowFn] {
const roundY = lcdKeySize + displayInfo.rowGap
const roundX = lcdKeySize + displayInfo.columnGap

const canDrawPixel = (x: number, y: number) => {
if (displayInfo.rowGap > 0 && (drawY + y) % roundY >= lcdKeySize) {
// Skip blanked rows
return false
}

if (displayInfo.columnGap > 0 && (drawX + x) % roundX >= lcdKeySize) {
// Skip blanked rows
return false
}

return true
}
const canDrawRow = (y: number) => {
if (displayInfo.rowGap > 0 && (drawY + y) % roundY >= lcdKeySize) {
// Skip blanked rows
return false
}

return true
}

return [canDrawPixel, canDrawRow]
}

export function encodeBuffer(
input: Buffer,
output: Buffer,
format: LoupedeckBufferFormat,
outputPadding: number,
pixelCount: number
width: number,
height: number,
canDrawPixel: CanDrawPixelFn,
canDrawRow: CanDrawRowFn
): void {
const pixelCount = width * height
if (input.length !== pixelCount * format.length)
throw new Error(`Incorrect buffer length ${input.length} expected ${pixelCount * format.length}`)
if (output.length !== pixelCount * 2 + outputPadding)
throw new Error(`Incorrect buffer length ${output.length} expected ${pixelCount * 2 + outputPadding}`)

switch (format) {
case LoupedeckBufferFormat.RGB:
for (let i = 0; i < pixelCount; i++) {
const r = input.readUInt8(i * 3 + 0) >> 3
const g = input.readUInt8(i * 3 + 1) >> 2
const b = input.readUInt8(i * 3 + 2) >> 3
output.writeUint16LE((r << 11) + (g << 5) + b, outputPadding + i * 2)
for (let y = 0; y < height; y++) {
if (!canDrawRow(y)) continue

for (let x = 0; x < width; x++) {
if (!canDrawPixel(x, y)) continue

const i = y * width + x
const r = input.readUInt8(i * 3 + 0) >> 3
const g = input.readUInt8(i * 3 + 1) >> 2
const b = input.readUInt8(i * 3 + 2) >> 3
output.writeUint16LE((r << 11) + (g << 5) + b, outputPadding + i * 2)
}
}
break
default:
Expand Down

0 comments on commit a133410

Please sign in to comment.