Merge pull request #195 from pimoroni/patch-ioexpander-delays

Slow set/clr_bit writes a little
This commit is contained in:
Philip Howard 2021-08-27 10:45:11 +01:00 committed by GitHub
commit d1ca596201
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 27 additions and 29 deletions

View File

@ -756,28 +756,20 @@ namespace pimoroni {
}
void IOExpander::set_bits(uint8_t reg, uint8_t bits) {
// Set the specified bits (using a mask) in a register.
// Deal with special case registers first
bool reg_in_bit_addressed_regs = false;
for(uint8_t i = 0; i < NUM_BIT_ADDRESSED_REGISTERS; i++) {
if(BIT_ADDRESSED_REGS[i] == reg) {
if(reg == reg::P0 || reg == reg::P1 || reg == reg::P2 || reg == reg::P3) {
for(uint8_t bit = 0; bit < 8; bit++) {
if(bits & (1 << bit))
if(bits & (1 << bit)) {
i2c->reg_write_uint8(address, reg, 0b1000 | (bit & 0b111));
sleep_us(50);
}
reg_in_bit_addressed_regs = true;
break;
}
return;
}
// Now deal with any other registers
if(!reg_in_bit_addressed_regs) {
uint8_t value = i2c->reg_read_uint8(address, reg);
sleep_us(10);
sleep_us(50);
i2c->reg_write_uint8(address, reg, value | bits);
}
}
void IOExpander::set_bit(uint8_t reg, uint8_t bit) {
// Set the specified bit (nth position from right) in a register.
@ -785,25 +777,21 @@ namespace pimoroni {
}
void IOExpander::clr_bits(uint8_t reg, uint8_t bits) {
bool reg_in_bit_addressed_regs = false;
for(uint8_t i = 0; i < NUM_BIT_ADDRESSED_REGISTERS; i++) {
if(BIT_ADDRESSED_REGS[i] == reg) {
if(reg == reg::P0 || reg == reg::P1 || reg == reg::P2 || reg == reg::P3) {
for(uint8_t bit = 0; bit < 8; bit++) {
if(bits & (1 << bit))
if(bits & (1 << bit)) {
i2c->reg_write_uint8(address, reg, 0b0000 | (bit & 0b111));
sleep_us(50);
}
reg_in_bit_addressed_regs = true;
break;
}
return;
}
// Now deal with any other registers
if(!reg_in_bit_addressed_regs) {
uint8_t value = i2c->reg_read_uint8(address, reg);
sleep_us(10);
sleep_us(50);
i2c->reg_write_uint8(address, reg, value & ~bits);
}
}
void IOExpander::clr_bit(uint8_t reg, uint8_t bit) {
// Clear the specified bit (nth position from right) in a register.

View File

@ -51,6 +51,16 @@ void APA102::update(bool blocking) {
dma_channel_set_read_addr(dma_channel, buffer, true);
if (!blocking) return;
while(dma_channel_is_busy(dma_channel)) {}; // Block waiting for DMA finish
// This is necessary to prevent a single LED remaining lit when clearing and updating.
// This code will only run in *blocking* mode since it's assumed non-blocking will be continuously updating anyway.
// Yes this will slow down LED updates... don't use blocking mode unless you're clearing LEDs before shutdown,
// or you *really* want to avoid actively driving your APA102s for some reason.
for(auto x = 0u; x < (num_leds / 16) + 1; x++) {
pio->txf[sm] = 0x00000000;
// Some delay is needed, since the PIO is async
// and this could be happening during a destructor/MicroPython soft reset
sleep_ms(1); // Chosen by fair dice roll
}
}
bool APA102::start(uint fps) {