const Gpio = require('onoff').Gpio; const i2c = require('i2c-bus'); const MAX9744_I2CADDR = 0x4b; const MAX_VOLUME = 63; const MIN_VOLUME = 0; const VOLUME_STEPS = 1; let currentVolume = MIN_VOLUME; let i2c1; async function readVolume() { const rBuf = Buffer.alloc(1); const data = await i2c1.i2cRead(MAX9744_I2CADDR, rBuf.length, rBuf); return data.buffer.readUInt8(); } async function writeVolume(volume) { const wBuf = Buffer.from([volume]); await i2c1.i2cWrite(MAX9744_I2CADDR, wBuf.length, wBuf); console.log("Volume set: ", volume); } async function increaseVolume() { console.log("Increasing volume"); currentVolume = currentVolume < MAX_VOLUME - VOLUME_STEPS ? currentVolume + VOLUME_STEPS : MAX_VOLUME; await writeVolume(currentVolume); } async function decreaseVolume() { console.log("Decreasing volume"); currentVolume = currentVolume > MIN_VOLUME + VOLUME_STEPS ? currentVolume - VOLUME_STEPS : MIN_VOLUME; await writeVolume(currentVolume); } async function handleButtonTick(button) { console.log("Handling button tick"); if(button.active) { await button.action(); button.cycles++; let timeout = 1400 - (button.cycles * 200); if(timeout < 200) { timeout = 200; } button.watcher = setTimeout(async () => { await handleButtonTick(button); }, timeout); } else if(button.watcher) { clearTimeout(button.watcher); button.cycles = 0; } } const buttons = { volumeUp: {pin: 17, gpio: null, active: false, watcher: null, action: increaseVolume, cycles: 0}, volumeDown: {pin: 27, gpio: null, active: false, watcher: null, action: decreaseVolume, cycles: 0} }; function watchButton(button) { button.gpio.watch(async (err, value) => { if(err) { button.active = false; if(button.watcher) { clearInterval(button.watcher); button.cycles = 0; } console.error(err); } else { if (value === 1) { button.active = true; await handleButtonTick(button); } else { button.active = false; if(button.watcher) { clearInterval(button.watcher); } } } }); } function initButton(button) { button.gpio = new Gpio(button.pin, 'in', 'both', { activeLow: true}); watchButton(button); } async function main() { try { i2c1 = await i2c.openPromisified(1); currentVolume = await readVolume(); initButton(buttons.volumeUp); initButton(buttons.volumeDown); } catch (err) { console.error(err); } } main();