Skip to content

Commit

Permalink
Merge pull request #195 from pimoroni/patch-ioexpander-delays
Browse files Browse the repository at this point in the history
Slow set/clr_bit writes a little
  • Loading branch information
Gadgetoid committed Aug 27, 2021
2 parents 07f3d65 + b5c7add commit d1ca596
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 29 deletions.
46 changes: 17 additions & 29 deletions drivers/ioexpander/ioexpander.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -756,27 +756,19 @@ 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);
i2c->reg_write_uint8(address, reg, value | bits);
}
uint8_t value = i2c->reg_read_uint8(address, reg);
sleep_us(50);
i2c->reg_write_uint8(address, reg, value | bits);
}

void IOExpander::set_bit(uint8_t reg, uint8_t bit) {
Expand All @@ -785,24 +777,20 @@ 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) {
for(uint8_t bit = 0; bit < 8; bit++) {
if(bits & (1 << bit))
i2c->reg_write_uint8(address, reg, 0b0000 | (bit & 0b111));
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)) {
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);
i2c->reg_write_uint8(address, reg, value & ~bits);
}
uint8_t value = i2c->reg_read_uint8(address, reg);
sleep_us(50);
i2c->reg_write_uint8(address, reg, value & ~bits);
}

void IOExpander::clr_bit(uint8_t reg, uint8_t bit) {
Expand Down
10 changes: 10 additions & 0 deletions drivers/plasma/apa102.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down

0 comments on commit d1ca596

Please sign in to comment.