diff options
| author | Uri Shaked | 2021-09-10 21:05:21 +0300 |
|---|---|---|
| committer | GitHub | 2021-09-10 21:05:21 +0300 |
| commit | ec1346b8a9766f95ff8aae7a3e6abf61307a7d7c (patch) | |
| tree | 95973ae705dffcb28930bbd4d189f21d8627d9cb /src/peripherals/adc.spec.ts | |
| parent | feat(watchdog): implement watchdog timer #106 (diff) | |
| download | avr8js-ec1346b8a9766f95ff8aae7a3e6abf61307a7d7c.tar.gz avr8js-ec1346b8a9766f95ff8aae7a3e6abf61307a7d7c.tar.bz2 avr8js-ec1346b8a9766f95ff8aae7a3e6abf61307a7d7c.zip | |
feat(adc): ADC peripheral #13
Diffstat (limited to '')
| -rw-r--r-- | src/peripherals/adc.spec.ts | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/src/peripherals/adc.spec.ts b/src/peripherals/adc.spec.ts new file mode 100644 index 0000000..4eb9aff --- /dev/null +++ b/src/peripherals/adc.spec.ts @@ -0,0 +1,137 @@ +import { CPU } from '../cpu/cpu'; +import { asmProgram, TestProgramRunner } from '../utils/test-utils'; +import { AVRADC, adcConfig, ADCMuxInputType } from './adc'; + +const R16 = 16; +const R17 = 17; + +const ADMUX = 0x7c; +const REFS0 = 1 << 6; + +const ADCSRA = 0x7a; +const ADEN = 1 << 7; +const ADSC = 1 << 6; +const ADPS0 = 1 << 0; +const ADPS1 = 1 << 1; +const ADPS2 = 1 << 2; + +const ADCH = 0x79; +const ADCL = 0x78; + +describe('ADC', () => { + it('should successfuly perform an ADC conversion', () => { + const { program } = asmProgram(` + ; register addresses + _REPLACE ADMUX, ${ADMUX} + _REPLACE ADCSRA, ${ADCSRA} + _REPLACE ADCH, ${ADCH} + _REPLACE ADCL, ${ADCL} + + ; Configure mux - channel 0, reference: AVCC with external capacitor at AREF pin + ldi r24, ${REFS0} + sts ADMUX, r24 + + ; Start conversion with 128 prescaler + ldi r24, ${ADEN | ADSC | ADPS0 | ADPS1 | ADPS2} + sts ADCSRA, r24 + + ; Wait until conversion is complete + waitComplete: + lds r24, ${ADCSRA} + andi r24, ${ADSC} + brne waitComplete + + ; Read the result + lds r16, ${ADCL} + lds r17, ${ADCH} + + break + `); + const cpu = new CPU(program); + const adc = new AVRADC(cpu, adcConfig); + const runner = new TestProgramRunner(cpu); + + const adcReadSpy = jest.spyOn(adc, 'onADCRead'); + adc.channelValues[0] = 2.56; // should result in 2.56/5*1024 = 524 + + // Setup + runner.runInstructions(4); + expect(adcReadSpy).toHaveBeenCalledWith({ channel: 0, type: ADCMuxInputType.SingleEnded }); + + // Run the "waitComplete" loop for a few cycles + runner.runInstructions(12); + + cpu.cycles += 128 * 25; // skip to the end of the conversion + cpu.tick(); + + // Now read the result + runner.runInstructions(5); + + const low = cpu.data[R16]; + const high = cpu.data[R17]; + expect((high << 8) | low).toEqual(524); // 2.56 volts - see above + }); + + it('should read 0 when the ADC peripheral is not enabled', () => { + // This behavior was verified on real hardware, using the following test program: + // https://wokwi.com/arduino/projects/309156042450666050 + // Thanks Oscar Oomens for spotting this! + + const { program } = asmProgram(` + ; register addresses + _REPLACE ADMUX, ${ADMUX} + _REPLACE ADCSRA, ${ADCSRA} + _REPLACE ADCH, ${ADCH} + _REPLACE ADCL, ${ADCL} + + ; Load some initial value into r16/r17 to make sure we actually read 0 later + ldi r16, 0xff + ldi r17, 0xff + + ; Configure mux - channel 0, reference: AVCC with external capacitor at AREF pin + ldi r24, ${REFS0} + sts ADMUX, r24 + + ; Start conversion with 128 prescaler, but without enabling the ADC + ldi r24, ${ADSC | ADPS0 | ADPS1 | ADPS2} + sts ADCSRA, r24 + + ; Wait until conversion is complete + waitComplete: + lds r24, ${ADCSRA} + andi r24, ${ADSC} + brne waitComplete + + ; Read the result + lds r16, ${ADCL} + lds r17, ${ADCH} + + break + `); + const cpu = new CPU(program); + const adc = new AVRADC(cpu, adcConfig); + const runner = new TestProgramRunner(cpu, () => { + /* do nothing on break */ + }); + + const adcReadSpy = jest.spyOn(adc, 'onADCRead'); + adc.channelValues[0] = 2.56; // should result in 2.56/5*1024 = 524 + + // Setup + runner.runInstructions(6); + expect(adcReadSpy).not.toHaveBeenCalled(); + + // Run the "waitComplete" loop for a few cycles + runner.runInstructions(12); + + cpu.cycles += 128 * 25; // skip to the end of the conversion + cpu.tick(); + + // Now read the result + runner.runToBreak(); + + const low = cpu.data[R16]; + const high = cpu.data[R17]; + expect((high << 8) | low).toEqual(0); // We should read 0 since the ADC hasn't been enabled + }); +}); |
