diff options
| author | Uri Shaked | 2021-12-13 11:35:26 +0200 |
|---|---|---|
| committer | Uri Shaked | 2021-12-13 11:35:26 +0200 |
| commit | 1d70883bc19cfda0ade132783a71d6e5fbaff79d (patch) | |
| tree | ee122443aea75a1f83f08f4882608122fbbd070e /src | |
| parent | 0.18.6 (diff) | |
| download | avr8js-1d70883bc19cfda0ade132783a71d6e5fbaff79d.tar.gz avr8js-1d70883bc19cfda0ade132783a71d6e5fbaff79d.tar.bz2 avr8js-1d70883bc19cfda0ade132783a71d6e5fbaff79d.zip | |
fix(twi): fails on repeated start condition
reproduction: https://wokwi.com/arduino/projects/306115576172905024
minimal reproduction code:
```cpp
#include <Wire.h>
void setup() {
Serial.begin(115200);
Wire.begin();
Wire.beginTransmission(0x68);
Wire.write( 0x3B);
Wire.endTransmission( false); // <---- Fails after this
auto n = Wire.requestFrom(0x68, 6);
if (n == 6) {
int16_t AcX = Wire.read() << 8 | Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
int16_t AcY = Wire.read() << 8 | Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
int16_t AcZ = Wire.read() << 8 | Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
Serial.print( "AcX = "); Serial.print( AcX);
Serial.print( " | AcY = "); Serial.print( AcY);
Serial.print( " | AcZ = "); Serial.print( AcZ);
Serial.println();
} else {
Serial.println( "--------- ERROR ---------");
}
}
void loop() {}
```
Diffstat (limited to 'src')
| -rw-r--r-- | src/peripherals/twi.ts | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/src/peripherals/twi.ts b/src/peripherals/twi.ts index 0dd8377..9af1749 100644 --- a/src/peripherals/twi.ts +++ b/src/peripherals/twi.ts @@ -94,6 +94,7 @@ export class NoopTWIEventHandler implements TWIEventHandler { export class AVRTWI { public eventHandler: TWIEventHandler = new NoopTWIEventHandler(this); + private busy = false; // Interrupts private TWI: AVRInterruptConfig = { @@ -112,18 +113,23 @@ export class AVRTWI { this.cpu.clearInterruptByFlag(this.TWI, value); this.cpu.updateInterruptEnable(this.TWI, value); const { status } = this; - if (clearInt && value & TWCR_TWEN) { + if (clearInt && value & TWCR_TWEN && !this.busy) { const twdrValue = this.cpu.data[this.config.TWDR]; this.cpu.addClockEvent(() => { if (value & TWCR_TWSTA) { + this.busy = true; this.eventHandler.start(status !== STATUS_TWI_IDLE); } else if (value & TWCR_TWSTO) { + this.busy = true; this.eventHandler.stop(); } else if (status === STATUS_START || status === STATUS_REPEATED_START) { + this.busy = true; this.eventHandler.connectToSlave(twdrValue >> 1, twdrValue & 0x1 ? false : true); } else if (status === STATUS_SLAW_ACK || status === STATUS_DATA_SENT_ACK) { + this.busy = true; this.eventHandler.writeByte(twdrValue); } else if (status === STATUS_SLAR_ACK || status === STATUS_DATA_RECEIVED_ACK) { + this.busy = true; const ack = !!(value & TWCR_TWEA); this.eventHandler.readByte(ack); } @@ -153,15 +159,18 @@ export class AVRTWI { } completeStart() { + this.busy = false; this.updateStatus(this.status === STATUS_TWI_IDLE ? STATUS_START : STATUS_REPEATED_START); } completeStop() { + this.busy = false; this.cpu.data[this.config.TWCR] &= ~TWCR_TWSTO; this.updateStatus(STATUS_TWI_IDLE); } completeConnect(ack: boolean) { + this.busy = false; if (this.cpu.data[this.config.TWDR] & 0x1) { this.updateStatus(ack ? STATUS_SLAR_ACK : STATUS_SLAR_NACK); } else { @@ -170,10 +179,12 @@ export class AVRTWI { } completeWrite(ack: boolean) { + this.busy = false; this.updateStatus(ack ? STATUS_DATA_SENT_ACK : STATUS_DATA_SENT_NACK); } completeRead(value: u8) { + this.busy = false; const ack = !!(this.cpu.data[this.config.TWCR] & TWCR_TWEA); this.cpu.data[this.config.TWDR] = value; this.updateStatus(ack ? STATUS_DATA_RECEIVED_ACK : STATUS_DATA_RECEIVED_NACK); |
