From 713f028d27a1be3868640d0667af7aebfe13528b Mon Sep 17 00:00:00 2001 From: Konstantin Begun Date: Wed, 10 May 2017 23:55:11 +0100 Subject: [PATCH] acomp: Add tests --- tests/atmega88_ac_test.c | 179 ++++++++++++++++++++++++++++++++++ tests/test_atmega88_ac_test.c | 34 +++++++ 2 files changed, 213 insertions(+) create mode 100755 tests/atmega88_ac_test.c create mode 100755 tests/test_atmega88_ac_test.c diff --git a/tests/atmega88_ac_test.c b/tests/atmega88_ac_test.c new file mode 100755 index 0000000..8b04f96 --- /dev/null +++ b/tests/atmega88_ac_test.c @@ -0,0 +1,179 @@ +/* + atmega88_ac_test.c + + Copyright 2017 Konstantin Begun + + This file is part of simavr. + + simavr is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + simavr is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with simavr. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +/* + * This demonstrate how to use the avr_mcu_section.h file + * The macro adds a section to the ELF file with useful + * information for the simulator + */ +#include "avr_mcu_section.h" +AVR_MCU(F_CPU, "atmega88"); + +static int uart_putchar(char c, FILE *stream) { + if (c == '\n') + uart_putchar('\r', stream); + loop_until_bit_is_set(UCSR0A, UDRE0); + UDR0 = c; + return 0; +} + +static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, + _FDEV_SETUP_WRITE); + +volatile uint8_t int_done; + +ISR(ANALOG_COMP_vect) +{ + int_done = 1; +} + +ISR(TIMER1_CAPT_vect) +{ + int_done = 2; +} + +static inline void output_value() { + putchar(ACSR & _BV(ACO) ? '1':'0'); +} + +static inline void output_test(uint8_t expected) { + putchar(int_done == expected ? 'Y':'N'); +} + +int main(void) +{ + stdout = &mystdout; + + sei(); + + ACSR = 0; + + printf("Check analog comparator with polling values\n"); + + // check all the inputs + for(uint8_t t = 0; t < 2; ++t) { // run twice, first with AIN0, second with bandgap + ADCSRB = 0; // multiplexer off + _NOP(); // for sync delay + output_value(); + // now with multiplexer + ADCSRB = _BV(ACME); + _NOP(); + for(uint8_t i = 0; i < 8;++i) + { + // this is relying that all 3 mux bits are next to each other, which is the case for atmega88 + output_value(); + ADMUX += _BV(MUX0); + _NOP(); + } + // switch to bandgap + ACSR |= _BV(ACBG); + _NOP(); + } + + putchar('\n'); + + // check interrupts + printf("Check analog comparator interrupts\n"); + // in this test bandgap is expected to be above ADC0 and below ADC1 + + ADCSRB = _BV(ACME); + ADMUX = 0; // ADC0 + ACSR = _BV(ACBG) | _BV(ACIE) | _BV(ACI); // enable interrupts on output triggering + + // switch to ADC1 + int_done = 0; + ADMUX = _BV(MUX0); + _delay_us(500); + output_test(1); + + // back to ADC0 + int_done = 0; + ADMUX = 0; + _delay_us(500); + output_test(1); + + // change to trigger on falling edge + ACSR = _BV(ACBG) | _BV(ACIE) | _BV(ACI) | _BV(ACIS1); + + // switch to ADC1 (falling edge) + int_done = 0; + ADMUX = _BV(MUX0); + _delay_us(500); + output_test(1); + + // switch to ADC0 (rising edge) + int_done = 0; + ADMUX = 0; + _delay_us(500); + output_test(0); // expect no interrupt + + // change to trigger on rising edge + ACSR = _BV(ACBG) | _BV(ACIE) | _BV(ACI) | _BV(ACIS1) | _BV(ACIS0); + + // switch to ADC1 (falling edge) + int_done = 0; + ADMUX = _BV(MUX0); + _delay_us(500); + output_test(0); // expect no interrupt + + // switch to ADC0 (rising edge) + int_done = 0; + ADMUX = 0; + _delay_us(500); + output_test(1); + + putchar('\n'); + + // now check timer1 input capture + printf("Check analog comparator triggering timer capture\n"); + // setup AC for rising edge, disable comparator own interrupt and enable timer1 capture + ACSR = _BV(ACBG) | _BV(ACIC) | _BV(ACIS1) | _BV(ACIS0); + + // now set up timer to capture on rising edge + TCCR1A = 0; + TCNT1 = 5555; + TIMSK1 = _BV(ICIE1); // enable capture interrupt + TCCR1B = _BV(ICES1) | _BV(CS10); + + // switch to ADC1 (falling edge) + int_done = 0; + ADMUX = _BV(MUX0); + _delay_us(500); + output_test(0); // expect no interrupt + + // switch to ADC0 (rising edge) + int_done = 0; + ADMUX = 0; + _delay_us(500); + output_test(2); + + cli(); + sleep_cpu(); + +} + diff --git a/tests/test_atmega88_ac_test.c b/tests/test_atmega88_ac_test.c new file mode 100755 index 0000000..666470b --- /dev/null +++ b/tests/test_atmega88_ac_test.c @@ -0,0 +1,34 @@ +#include "tests.h" +#include "avr_acomp.h" + +int main(int argc, char **argv) { + tests_init(argc, argv); + + static const char *expected = + "Check analog comparator with polling values\r\n" + "110110101010000100\r\n" + "Check analog comparator interrupts\r\n" + "YYYYYY\r\n" + "Check analog comparator triggering timer capture\r\n" + "YY"; + + avr_t *avr = tests_init_avr("atmega88_ac_test.axf"); + + // set voltages + avr_raise_irq(avr_io_getirq(avr, AVR_IOCTL_ACOMP_GETIRQ, ACOMP_IRQ_AIN0), 2000); + avr_raise_irq(avr_io_getirq(avr, AVR_IOCTL_ACOMP_GETIRQ, ACOMP_IRQ_AIN1), 1800); + avr_raise_irq(avr_io_getirq(avr, AVR_IOCTL_ACOMP_GETIRQ, ACOMP_IRQ_ADC0), 200); + avr_raise_irq(avr_io_getirq(avr, AVR_IOCTL_ACOMP_GETIRQ, ACOMP_IRQ_ADC1), 3000); + avr_raise_irq(avr_io_getirq(avr, AVR_IOCTL_ACOMP_GETIRQ, ACOMP_IRQ_ADC2), 1500); + avr_raise_irq(avr_io_getirq(avr, AVR_IOCTL_ACOMP_GETIRQ, ACOMP_IRQ_ADC3), 1500); + avr_raise_irq(avr_io_getirq(avr, AVR_IOCTL_ACOMP_GETIRQ, ACOMP_IRQ_ADC4), 3000); + avr_raise_irq(avr_io_getirq(avr, AVR_IOCTL_ACOMP_GETIRQ, ACOMP_IRQ_ADC5), 200); + avr_raise_irq(avr_io_getirq(avr, AVR_IOCTL_ACOMP_GETIRQ, ACOMP_IRQ_ADC6), 3000); + avr_raise_irq(avr_io_getirq(avr, AVR_IOCTL_ACOMP_GETIRQ, ACOMP_IRQ_ADC7), 1500); + + tests_assert_uart_receive_avr(avr, 100000, + expected, '0'); + + tests_success(); + return 0; +} -- 2.39.5