diff --git a/Makefile b/Makefile index 5e016ca..262f5e7 100644 --- a/Makefile +++ b/Makefile @@ -107,6 +107,8 @@ smoke-test: @md5sum ./build/test.hex tinygo build -size short -o ./build/test.hex -target=p1am-100 ./examples/p1am/main.go @md5sum ./build/test.hex + tinygo build -size short -o ./build/test.hex -target=pico ./examples/pca9685/main.go + @md5sum ./build/test.hex tinygo build -size short -o ./build/test.hex -target=microbit ./examples/pcd8544/setbuffer/main.go @md5sum ./build/test.hex tinygo build -size short -o ./build/test.hex -target=microbit ./examples/pcd8544/setpixel/main.go diff --git a/pca9685/pca9685_buffered.go b/pca9685/pca9685_buffered.go new file mode 100644 index 0000000..c741192 --- /dev/null +++ b/pca9685/pca9685_buffered.go @@ -0,0 +1,53 @@ +package pca9685 + +import ( + "encoding/binary" + + "tinygo.org/x/drivers" +) + +// 16 PWM channels, 2 2 byte values each (on, off 16bits) +const buffLen = 16 * 2 * 2 + +// DevBuffered provides a way of performing one-shot writes +// on all PWM signals. This is useful when working with systems +// which require as little as possible I/O overhead. +type DevBuffered struct { + Dev + // LED buffer, first value is address, following values correspond to LED registers. + // [0]: LEDSTART register address + // [1:5]: LED0 corresponding to PWM channel 0 + // [5:9]: LED1 PWM channel 1 + // ... + // [1 + N*4 : 1 + N*4 + 4] : channnel N up to channel 15 + ledBuf [buffLen + 1]byte +} + +// New creates a new instance of a PCA9685 device. It performs +// no IO on the i2c bus. +func NewBuffered(bus drivers.I2C, addr uint8) *DevBuffered { + db := &DevBuffered{ + Dev: New(bus, addr), + } + db.ledBuf[0] = LEDSTART + return db +} + +// PrepSet prepares a value to be written to the +// channel's PWM register on Update() call. +func (b *DevBuffered) PrepSet(channel uint8, on uint32) { + b.PrepPhasedSet(channel, on, 0) +} + +// PrepPhasedSet prepares a phased PWM value to be written to the +// channel's register on Update() call. +func (b *DevBuffered) PrepPhasedSet(channel uint8, on, off uint32) { + onLReg := 1 + channel*4 + binary.LittleEndian.PutUint16(b.ledBuf[onLReg:], uint16(on)&maxtop) + binary.LittleEndian.PutUint16(b.ledBuf[onLReg+2:], uint16(off)&maxtop) +} + +// Update writes the prepared values to the PWM device registers in one shot. +func (b *DevBuffered) Update() error { + return b.bus.Tx(uint16(b.addr), b.ledBuf[:], nil) +}