HWA
Bare metal programming with style
hwa/atmel/avr/examples/06-1-swuart-adc/main.c
Transmit ADC conversion results through software UART

Send '\r'+ 4 hex characters of last ADC conversion every 20 ms

Test application

Display the ADC result on the command line:

 ./main.py

You can add a low-pass filtering with the --lpf option.

Display the ADC result on a graphical dial (requires wxPython):

 ./main.py --gfx

Dial

config.h
#ifndef CONFIG_H
#define CONFIG_H
#include BOARD_H
#define UART HW_SWUARTA( txd, DIABOLO_PIN_TX, \
rxd, DIABOLO_PIN_RX, \
startirq, (DIABOLO_PIN_RX,port,pcic,irq), \
counter, counter1, \
compare, compare0, \
clkdiv, 1, \
autosync, 51, \
fastreg, (shared,gpior0) )
HW_DECLARE(UART);
#endif
main.c
/* This file is part of the HWA project.
* Copyright (c) 2012,2015 Christophe Duparquet.
* All rights reserved. Read LICENSE.TXT for details.
*/
#include "config.h"
/* Use pin AVCC as Vref when possible
*/
#if HW_ADDRESS((pin,avcc)) == -1
# define VREF vcc
#else
# define VREF (pin,avcc)
#endif
/* The counter used to schedule the ADC conversions
*
* FIXME: using the same counter as for swuart overrides the configuration
* without error!
*/
#define COUNTER counter0
volatile uint16_t adc ; // Last adc value
volatile uint8_t x_adc ; // Set to 1 after adc is written
void uart_putbyte ( uint8_t byte )
{
while ( !hw(stat,UART).txc )
hw( wait, irq );
hw( write, UART, byte );
}
/* Service counter overflow interrupt:
* turn the ADC on, it will start a conversion as the MCU enters sleep
*/
HW_ISR( (COUNTER,irq,overflow) )
{
hw( enable, adc0 );
hw( toggle, PIN_LED );
}
/* Service ADC conversion interrupt:
* get ADC result, stop the ADC, signal new data ready
*/
HW_ISR( (adc0,irq) )
{
adc = hw( read, adc0 );
hw( disable, adc0 );
x_adc = 1 ;
}
int
main ( )
{
/* Create a HWA context to collect the hardware configuration
* Preload this context with RESET values
*/
hwa( begin, reset );
/* Configure the software UART
*/
hwa( configure, UART );
/* Configure LED pin
*/
hwa( configure, PIN_LED, mode, digital_output );
/* Have the CPU enter idle mode when the 'sleep' instruction is executed.
*/
hwa( configure, core0,
sleep, enabled,
sleep_mode, idle );
/* Configure the counter to overflow every ~0.02 s.
*
* The compare unit `compare0` (OCRxA) is used to store the top value.
* Unless otherwise stated, the overflow will be automatically set to occur
* at top in `up_loop` counting mode, and at bottom in `updown_loop` counting
* mode.
*
* We use the updown_loop counting mode so that an 8-bit counter can handle
* the delay at 16 MHz.
*/
hwa( configure, COUNTER,
clock, ioclk / 1024,
direction, updown_loop,
bottom, 0,
top, compare0 );
hwa( write, (COUNTER,compare0), 0.02 * HW_SYSHZ / 1024 / 2 );
hwa( enable, (COUNTER,irq,overflow) );
/* Configure the ADC (this turns it on)
*/
hwa( configure, adc0,
clock, ioclk / 128,
trigger, manual,
vref, VREF,
align, right,
input, PIN_ANALOG_INPUT );
hwa( enable, (adc0,irq) );
/* Write this configuration into the hardware
*/
hwa( commit );
hw( enable, interrupts );
/* Wait for UART synchronization, then send the prompt
*/
while ( !hw(stat,UART).sync )
hw( wait, irq );
hw( write, UART, '$' );
/* Main loop:
* Enter sleep mode
* Send new data to host
*/
for(;;) {
hw( wait, irq );
if ( x_adc ) {
uint16_t x ;
do {
x_adc = 0 ;
x = adc ;
} while( x_adc );
uart_putbyte( (x & 0x00FF)>>0 );
uart_putbyte( (x & 0xFF00)>>8 );
}
}
}
hwa
#define hwa(...)
hwa( action, object [,...] ) stores an action for an object into a HWA context.
Definition: hwa_macros.h:552
HW_DECLARE
#define HW_DECLARE(...)
Declares the functions that implement an object.
Definition: hwa_1.h:521
swuarta.h
Software-emulated UART.
hw
#define hw(...)
hw( action, object [,...] ) executes an action immediately on an object.
Definition: hwa_macros.h:523
PIN_ANALOG_INPUT
#define PIN_ANALOG_INPUT
Definition: attiny84.h:98
HW_ISR
#define HW_ISR(...)
Definition: hwa_interrupts.h:80