Commit 713f028d27a1be3868640d0667af7aebfe13528b
authorKonstantin Begun <kostic2000@gmail.com>
Wed, 10 May 2017 22:55:11 +0000 (23:55 +0100)
committerMichel Pollet <github.com@pollet.net>
Thu, 11 May 2017 06:59:48 +0000 (07:59 +0100)
2 files changed:
tests/atmega88_ac_test.c [new file with mode: 0755]
tests/test_atmega88_ac_test.c [new file with mode: 0755]

diff --git a/tests/atmega88_ac_test.c b/tests/atmega88_ac_test.c
new file mode 100755 (executable)
index 0000000..8b04f96
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <avr/io.h>
+#include <stdio.h>
+#include <avr/interrupt.h>
+#include <avr/sleep.h>
+#include <util/delay.h>
+#include <avr/cpufunc.h>
+
+/*
+ * 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 (executable)
index 0000000..666470b
--- /dev/null
@@ -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;
+}