diff options
| author | Uri Shaked | 2020-03-22 21:12:03 +0200 |
|---|---|---|
| committer | GitHub | 2020-03-22 21:12:03 +0200 |
| commit | b3dc0329a8a7bfb8350ddc71719d4348dd4ed66c (patch) | |
| tree | e85d52944ce76ac604e276f25859a26d38a0afd0 /src/peripherals/usart.spec.ts | |
| parent | Merge pull request #25 from LironHazan/AVR8JS-24-editor-user-history (diff) | |
| parent | refactor: added peripherals and cpu feature folders (diff) | |
| download | avr8js-b3dc0329a8a7bfb8350ddc71719d4348dd4ed66c.tar.gz avr8js-b3dc0329a8a7bfb8350ddc71719d4348dd4ed66c.tar.bz2 avr8js-b3dc0329a8a7bfb8350ddc71719d4348dd4ed66c.zip | |
Merge pull request #22 from LironHazan/AVR8JS-21-restructure-project
refactor: add peripherals and cpu feature folders
Diffstat (limited to 'src/peripherals/usart.spec.ts')
| -rw-r--r-- | src/peripherals/usart.spec.ts | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/src/peripherals/usart.spec.ts b/src/peripherals/usart.spec.ts new file mode 100644 index 0000000..d9843dc --- /dev/null +++ b/src/peripherals/usart.spec.ts @@ -0,0 +1,159 @@ +import { CPU } from '../cpu/cpu'; +import { AVRUSART, usart0Config } from './usart'; + +const FREQ_16MHZ = 16e6; +const FREQ_11_0529MHZ = 11059200; + +describe('USART', () => { + it('should correctly calculate the baudRate from UBRR', () => { + const cpu = new CPU(new Uint16Array(1024)); + const usart = new AVRUSART(cpu, usart0Config, FREQ_11_0529MHZ); + cpu.writeData(0xc5, 0); // UBRR0H <- 0 + cpu.writeData(0xc4, 5); // UBRR0L <- 5 + expect(usart.baudRate).toEqual(115200); + }); + + it('should correctly calculate the baudRate from UBRR in double-speed mode', () => { + const cpu = new CPU(new Uint16Array(1024)); + const usart = new AVRUSART(cpu, usart0Config, FREQ_16MHZ); + cpu.writeData(0xc5, 3); // UBRR0H <- 3 + cpu.writeData(0xc4, 64); // UBRR0L <- 64 + cpu.writeData(0xc0, 2); // UCSR0A: U2X0 + expect(usart.baudRate).toEqual(2400); + }); + + it('should return 5-bits per byte when UCSZ = 0', () => { + const cpu = new CPU(new Uint16Array(1024)); + const usart = new AVRUSART(cpu, usart0Config, FREQ_16MHZ); + cpu.writeData(0xc0, 0); + expect(usart.bitsPerChar).toEqual(5); + }); + + it('should return 6-bits per byte when UCSZ = 1', () => { + const cpu = new CPU(new Uint16Array(1024)); + const usart = new AVRUSART(cpu, usart0Config, FREQ_16MHZ); + cpu.writeData(0xc0, 0x2); + expect(usart.bitsPerChar).toEqual(6); + }); + + it('should return 7-bits per byte when UCSZ = 2', () => { + const cpu = new CPU(new Uint16Array(1024)); + const usart = new AVRUSART(cpu, usart0Config, FREQ_16MHZ); + cpu.writeData(0xc0, 0x4); + expect(usart.bitsPerChar).toEqual(7); + }); + + it('should return 8-bits per byte when UCSZ = 3', () => { + const cpu = new CPU(new Uint16Array(1024)); + const usart = new AVRUSART(cpu, usart0Config, FREQ_16MHZ); + cpu.writeData(0xc0, 0x6); + expect(usart.bitsPerChar).toEqual(8); + }); + + it('should return 9-bits per byte when UCSZ = 7', () => { + const cpu = new CPU(new Uint16Array(1024)); + const usart = new AVRUSART(cpu, usart0Config, FREQ_16MHZ); + cpu.writeData(0xc0, 0x6); + 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)); + 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 + }); + }); + + describe('onLineTransmit', () => { + it('should call onLineTransmit with the current line buffer after every newline', () => { + const cpu = new CPU(new Uint16Array(1024)); + const usart = new AVRUSART(cpu, usart0Config, FREQ_16MHZ); + usart.onLineTransmit = jest.fn(); + cpu.writeData(0xc1, 0x8); // UCSR0B <- TXEN + cpu.writeData(0xc6, 0x48); // 'H' + cpu.writeData(0xc6, 0x65); // 'e' + cpu.writeData(0xc6, 0x6c); // 'l' + cpu.writeData(0xc6, 0x6c); // 'l' + cpu.writeData(0xc6, 0x6f); // 'o' + cpu.writeData(0xc6, 0xa); // '\n' + expect(usart.onLineTransmit).toHaveBeenCalledWith('Hello'); + }); + + it('should not call onLineTransmit if no newline was received', () => { + const cpu = new CPU(new Uint16Array(1024)); + const usart = new AVRUSART(cpu, usart0Config, FREQ_16MHZ); + usart.onLineTransmit = jest.fn(); + cpu.writeData(0xc1, 0x8); // UCSR0B <- TXEN + cpu.writeData(0xc6, 0x48); // 'H' + cpu.writeData(0xc6, 0x69); // 'i' + expect(usart.onLineTransmit).not.toHaveBeenCalled(); + }); + + it('should clear the line buffer after each call to onLineTransmit', () => { + const cpu = new CPU(new Uint16Array(1024)); + const usart = new AVRUSART(cpu, usart0Config, FREQ_16MHZ); + usart.onLineTransmit = jest.fn(); + cpu.writeData(0xc1, 0x8); // UCSR0B <- TXEN + cpu.writeData(0xc6, 0x48); // 'H' + cpu.writeData(0xc6, 0x69); // 'i' + cpu.writeData(0xc6, 0xa); // '\n' + cpu.writeData(0xc6, 0x74); // 't' + cpu.writeData(0xc6, 0x68); // 'h' + cpu.writeData(0xc6, 0x65); // 'e' + cpu.writeData(0xc6, 0x72); // 'r' + cpu.writeData(0xc6, 0x65); // 'e' + cpu.writeData(0xc6, 0xa); // '\n' + expect(usart.onLineTransmit).toHaveBeenCalledWith('there'); + }); + }); +}); |
