aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/usart.spec.ts56
-rw-r--r--src/usart.ts2
2 files changed, 57 insertions, 1 deletions
diff --git a/src/usart.spec.ts b/src/usart.spec.ts
index 230709f..f0dacc4 100644
--- a/src/usart.spec.ts
+++ b/src/usart.spec.ts
@@ -57,4 +57,60 @@ describe('USART', () => {
cpu.writeData(0xc1, 0x4);
expect(usart.bitsPerChar).toEqual(9);
});
+
+ it('should invoke onByteTransmit when UDR0 is written to', () => {
+ const cpu = new CPU(new Uint16Array(1024));
+ const usart = new AVRUSART(cpu, usart0Config, FREQ_16MHZ);
+ usart.onByteTransmit = jest.fn();
+ cpu.writeData(0xc1, 0x8); // UCSR0B <- TXEN
+ cpu.writeData(0xc6, 0x61); // UDR0
+ expect(usart.onByteTransmit).toHaveBeenCalledWith(0x61);
+ });
+
+ it('should set UDRE and TXC flags after UDR0', () => {
+ const cpu = new CPU(new Uint16Array(1024));
+ const usart = new AVRUSART(cpu, usart0Config, FREQ_16MHZ);
+ cpu.writeData(0xc1, 0x8); // UCSR0B <- TXEN
+ cpu.writeData(0xc0, 0); // UCSR0A <- 0
+ cpu.writeData(0xc6, 0x61); // UDR0
+ expect(cpu.data[0xc0]).toEqual(0x40 | 0x20); // UCSR0A: TXC | UDRE
+ });
+
+ describe('tick()', () => {
+ it('should trigger data register empty interrupt if UDRE is set', () => {
+ const cpu = new CPU(new Uint16Array(1024));
+ const usart = new AVRUSART(cpu, usart0Config, FREQ_16MHZ);
+ cpu.writeData(0xc1, 0x28); // UCSR0B <- UDRIE | TXEN
+ cpu.writeData(0xc6, 0x61); // UDR0
+ cpu.data[95] = 0x80; // SREG: I-------
+ usart.tick();
+ expect(cpu.pc).toEqual(0x26);
+ expect(cpu.cycles).toEqual(2);
+ expect(cpu.data[0xc0] & 0x20).toEqual(0); // UCSR0A should clear UDRE
+ });
+
+ it('should trigger data tx complete interrupt if TXCIE is set', () => {
+ const cpu = new CPU(new Uint16Array(1024));
+ const usart = new AVRUSART(cpu, usart0Config, FREQ_16MHZ);
+ cpu.writeData(0xc1, 0x48); // UCSR0B <- TXCIE | TXEN
+ cpu.writeData(0xc6, 0x61); // UDR0
+ cpu.data[95] = 0x80; // SREG: I-------
+ usart.tick();
+ expect(cpu.pc).toEqual(0x28);
+ expect(cpu.cycles).toEqual(2);
+ expect(cpu.data[0xc0] & 0x40).toEqual(0); // UCSR0A should clear TXC
+ });
+
+ it('should not trigger any interrupt if interrupts are disabled', () => {
+ const cpu = new CPU(new Uint16Array(1024));
+ const usart = new AVRUSART(cpu, usart0Config, FREQ_16MHZ);
+ cpu.writeData(0xc1, 0x28); // UCSR0B <- UDRIE | TXEN
+ cpu.writeData(0xc6, 0x61); // UDR0
+ cpu.data[95] = 0; // SREG: 0 (disable interrupts)
+ usart.tick();
+ expect(cpu.pc).toEqual(0);
+ expect(cpu.cycles).toEqual(0);
+ expect(cpu.data[0xc0]).toEqual(0x40 | 0x20); // UCSR0A: TXC | UDRE
+ });
+ });
});
diff --git a/src/usart.ts b/src/usart.ts
index 276207e..da5cee0 100644
--- a/src/usart.ts
+++ b/src/usart.ts
@@ -59,7 +59,7 @@ export class AVRUSART {
public onByteTransmit: USARTTransmitCallback | null = null;
constructor(private cpu: CPU, private config: USARTConfig, private freqMHz: number) {
- this.cpu.writeHooks[config.UCSRA] = (value, oldValue) => {
+ this.cpu.writeHooks[config.UCSRA] = (value) => {
this.cpu.data[config.UCSRA] = value | UCSRA_UDRE | UCSRA_TXC;
return true;
};