1/* Copyright (c) 2005,2007 Joerg Wunsch 2 All rights reserved. 3 4 Redistribution and use in source and binary forms, with or without 5 modification, are permitted provided that the following conditions are met: 6 7 * Redistributions of source code must retain the above copyright 8 notice, this list of conditions and the following disclaimer. 9 10 * Redistributions in binary form must reproduce the above copyright 11 notice, this list of conditions and the following disclaimer in 12 the documentation and/or other materials provided with the 13 distribution. 14 15 * Neither the name of the copyright holders nor the names of 16 contributors may be used to endorse or promote products derived 17 from this software without specific prior written permission. 18 19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 POSSIBILITY OF SUCH DAMAGE. */ 30 31/* $Id: largedemo.dox 1190 2007-01-19 22:17:10Z joerg_wunsch $ */ 32 33/** \defgroup largedemo A more sophisticated project 34 \ingroup demos 35 36This project extends the basic idea of the 37\ref demo_project "simple project" to control a LED with a PWM 38output, but adds methods to adjust the LED brightness. 39It employs a lot of the basic concepts of avr-libc to achieve 40that goal. 41 42Understanding this project assumes the simple project has been 43understood in full, as well as being acquainted with the basic 44hardware concepts of an AVR microcontroller. 45 46\section largedemo_hw Hardware setup 47 48The demo is set up in a way so it can be run on the ATmega16 that 49ships with the STK500 development kit. The only external part needed 50is a potentiometer attached to the ADC. It is connected to a 10-pin 51ribbon cable for port A, both ends of the potentiometer to pins 9 52(GND) and 10 (VCC), and the wiper to pin 1 (port A0). 53A bypass capacitor from pin 1 to pin 9 (like 47 nF) is recommendable. 54 55\image html largedemo-setup.jpg "Setup of the STK500" 56\image latex largedemo-setup.eps "Setup of the STK500" width=12cm 57 58The coloured patch cables are used to provide various 59interconnections. As there are only four of them in the STK500, there 60are two options to connect them for this demo. The second option for 61the yellow-green cable is shown in parenthesis in the table. 62Alternatively, the "squid" cable from the JTAG ICE kit can be used if 63available. 64 65<table> 66 <tr><td><b>Port</b></td><td><b>Header</b></td><td><b>Color</b></td><td><b>Function</b></td><td><b>Connect to</b></td></tr> 67 <tr><td>D0</td> <td>1</td> <td>brown</td> <td>RxD</td> <td>RXD of the RS-232 header</td></tr> 68 <tr><td>D1</td> <td>2</td> <td>grey</td> <td>TxD</td> <td>TXD of the RS-232 header</td></tr> 69 <tr><td>D2</td> <td>3</td> <td>black</td> <td>button "down"</td> <td>SW0 (pin 1 switches header)</td></tr> 70 <tr><td>D3</td> <td>4</td> <td>red</td> <td>button "up"</td> <td>SW1 (pin 2 switches header)</td></tr> 71 <tr><td>D4</td> <td>5</td> <td>green</td> <td>button "ADC"</td> <td>SW2 (pin 3 switches header)</td></tr> 72 <tr><td>D5</td> <td>6</td> <td>blue</td> <td>LED</td> <td>LED0 (pin 1 LEDs header)</td></tr> 73 <tr><td>D6</td> <td>7</td> <td>(green)</td><td>clock out</td> <td>LED1 (pin 2 LEDs header)</td></tr> 74 <tr><td>D7</td> <td>8</td> <td>white</td> <td>1-second flash</td><td>LED2 (pin 3 LEDs header)</td></tr> 75 <tr><td>GND</td><td>9</td> <td></td> <td>unused</td></tr> 76 <tr><td>VCC</td><td>10</td><td></td> <td>unused</td></tr> 77</table> 78 79\image html largedemo-wiring.jpg "Wiring of the STK500" 80\image latex largedemo-wiring.eps "Wiring of the STK500" width=12cm 81 82The following picture shows the alternate wiring where LED1 is 83connected but SW2 is not: 84 85\image html largedemo-wiring2.jpg "Wiring option #2 of the STK500" 86\image latex largedemo-wiring2.eps "Wiring option #2 of the STK500" width=12cm 87 88As an alternative, this demo can also be run on the popular ATmega8 89controller, or its successor ATmega88 as well as the ATmega48 and 90ATmega168 variants of the latter. These controllers do not have a 91port named "A", so their ADC inputs are located on port C instead, 92thus the potentiometer needs to be attached to port C. Likewise, the 93OC1A output is not on port D pin 5 but on port B pin 1 (PB1). Thus, 94the above cabling scheme needs to be changed so that PB1 connects to 95the LED0 pin. (PD6 remains unconnected.) When using the STK500, use 96one of the jumper cables for this connection. All other port D pins 97should be connected the same way as described for the ATmega16 above. 98 99When not using an STK500 starter kit, attach the LEDs through some 100resistor to Vcc (low-active LEDs), and attach pushbuttons from the 101respective input pins to GND. The internal pull-up resistors are 102enabled for the pushbutton pins, so no external resistors are needed. 103 104Finally, the demo has been ported to the ATtiny2313 as well. As this 105AVR does not offer an ADC, everything related to handling the ADC is 106disabled in the code for that MCU type. Also, port D of this 107controller type only features 6 pins, so the 1-second flash LED had to 108be moved from PD6 to PD4. (PD4 is used as the ADC control button on 109the other MCU types, but that is not needed here.) OC1A is located at 110PB3 on this device. 111 112The \c MCU_TARGET macro in the Makefile needs to be adjusted 113appropriately for the alternative controller types. 114 115The flash ROM and RAM consumption of this demo are way below the 116resources of even an ATmega48, and still well within the capabilities 117of an ATtiny2313. 118The major advantage of experimenting 119with the ATmega16 (in addition that it ships together with an STK500 120anyway) is that it can be debugged online via JTAG. 121Likewise, the ATmega48/88/168 and ATtiny2313 devices can be debugged 122through debugWire, using the Atmel JTAG ICE mkII or the low-cost 123AVR Dragon. 124 125Note that in the explanation below, all port/pin names are applicable 126to the ATmega16 setup. 127 128\section largedemo_overview Functional overview 129 130PD6 will be toggled with each internal clock tick (approx. 10 131ms). PD7 will flash once per second. 132 133PD0 and PD1 are configured as UART IO, and can be used to connect the 134demo kit to a PC (9600 Bd, 8N1 frame format). The demo application 135talks to the serial port, and it can be controlled from the serial 136port. 137 138PD2 through PD4 are configured as inputs, and control the 139application unless control has been taken over by the serial 140port. Shorting PD2 to GND will decrease the current PWM value, 141shorting PD3 to GND will increase it. 142 143While PD4 is shorted to GND, one ADC conversion for channel 0 (ADC 144input is on PA0) will be triggered each internal clock tick, and 145the resulting value will be used as the PWM value. So the 146brightness of the LED follows the analog input value on PC0. VAREF 147on the STK500 should be set to the same value as VCC. 148 149When running in serial control mode, the function of the 150watchdog timer can be demonstrated by typing an `r'. This will 151make the demo application run in a tight loop without retriggering 152the watchdog so after some seconds, the watchdog will reset the 153MCU. This situation can be figured out on startup by reading the 154MCUCSR register. 155 156The current value of the PWM is backed up in an EEPROM cell after 157about 3 seconds of idle time after the last change. If that EEPROM 158cell contains a reasonable (i. e. non-erased) value at startup, it is 159taken as the initial value for the PWM. This virtually preserves the 160last value across power cycles. By not updating the EEPROM 161immmediately but only after a timeout, EEPROM wear is reduced 162considerably compared to immediately writing the value at each change. 163 164\section largedemo_code A code walkthrough 165 166This section explains the ideas behind individual parts of the code. 167The \ref largedemo_src "source code" has been divided into numbered 168parts, and the following subsections explain each of these parts. 169 170\subsection largedemo_code_p1 Part 1: Macro definitions 171 172A number of preprocessor macros are defined to improve readability 173and/or portability of the application. 174 175The first macros describe the IO pins our LEDs and pushbuttons are 176connected to. This provides some kind of mini-HAL (hardware 177abstraction layer) so should some of the connections be changed, they 178don't need to be changed inside the code but only on top. Note that 179the location of the PWM output itself is mandated by the hardware, so 180it cannot be easily changed. As the ATmega48/88/168 controllers 181belong to a more recent generation of AVRs, a number of register and 182bit names have been changed there, so they are mapped back to their 183ATmega8/16 equivalents to keep the actual program code portable. 184 185The name \c F_CPU is the conventional name to describe the CPU clock 186frequency of the controller. This demo project just uses the internal 187calibrated 1 MHz RC oscillator that is enabled by default. Note that 188when using the <tt><util/delay.h></tt> functions, \c F_CPU needs 189to be defined before including that file. 190 191The remaining macros have their own comments in the source code. The 192macro \c TMR1_SCALE shows how to use the preprocessor and the 193compiler's constant expression computation to calculate the value of 194timer 1's post-scaler in a way so it only depends on \c F_CPU and the 195desired software clock frequency. While the formula looks a bit 196complicated, using a macro offers the advantage that the application 197will automatically scale to new target softclock or master CPU 198frequencies without having to manually re-calculate hardcoded 199constants. 200 201\subsection largedemo_code_p2 Part 2: Variable definitions 202 203The \c intflags structure demonstrates a way to allocate bit variables 204in memory. Each of the interrupt service routines just sets one bit 205within that structure, and the application's main loop then monitors 206the bits in order to act appropriately. 207 208Like all variables that are used to communicate values between an 209interrupt service routine and the main application, it is declared 210\ref faq_volatile "volatile". 211 212The variable \c ee_pwm is not a variable in the classical C sense that 213could be used as an lvalue or within an expression to obtain its 214value. Instead, the 215 216\code __attribute__((section(".eeprom"))) \endcode 217 218marks it as belonging to the \ref sec_dot_eeprom "EEPROM section". 219This section is merely used as a placeholder so the compiler can 220arrange for each individual variable's location in EEPROM. The 221compiler will also keep track of initial values assigned, and usually 222the Makefile is arranged to extract these initial values into a 223separate load file (\c largedemo_eeprom.* in this case) that can be 224used to initialize the EEPROM. 225 226The actual EEPROM IO must be performed manually. 227 228Similarly, the variable \c mcucsr is kept in the 229\ref sec_dot_noinit ".noinit" section in order to prevent it from 230being cleared upon application startup. 231 232\subsection largedemo_code_p3 Part 3: Interrupt service routines 233 234The ISR to handle timer 1's overflow interrupt arranges for the 235software clock. While timer 1 runs the PWM, it calls its overflow 236handler rather frequently, so the \c TMR1_SCALE value is used as a 237postscaler to reduce the internal software clock frequency further. 238If the software clock triggers, it sets the \c tmr_int bitfield, 239and defers all further tasks to the main loop. 240 241The ADC ISR just fetches the value from the ADC conversion, disables 242the ADC interrupt again, and announces the presence of the new value 243in the \c adc_int bitfield. The interrupt is kept disabled while not 244needed, because the ADC will also be triggered by executing the SLEEP 245instruction in idle mode (which is the default sleep mode). Another 246option would be to turn off the ADC completely here, but that 247increases the ADC's startup time (not that it would matter much for 248this application). 249 250\subsection largedemo_code_p4 Part 4: Auxiliary functions 251 252The function \c handle_mcucsr() uses two \c __attribute__ declarators 253to achieve specific goals. First, it will instruct the compiler to 254place the generated code into the \ref sec_dot_init ".init3" section 255of the output. Thus, it will become part of the application 256initialization sequence. This is done in order to fetch (and clear) 257the reason of the last hardware reset from \c MCUCSR as early as 258possible. There is a short period of time where the next reset could 259already trigger before the current reason has been evaluated. This 260also explains why the variable \c mcucsr that mirrors the register's 261value needs to be placed into the .noinit section, because otherwise 262the default initialization (which happens after .init3) would blank 263the value again. 264 265As the initialization code is not called using CALL/RET instructions 266but rather concatenated together, the compiler needs to be instructed 267to omit the entire function prologue and epilogue. This is performed 268by the \e naked attribute. So while syntactically, \c handle_mcucsr() 269is a function to the compiler, the compiler will just emit the 270instructions for it without setting up any stack frame, and not even a RET instruction 271at the end. 272 273Function \c ioinit() centralizes all hardware setup. The very last 274part of that function demonstrates the use of the EEPROM variable \c 275ee_pwm to obtain an EEPROM address that can in turn be applied as an 276argument to \c eeprom_read_word(). 277 278The following functions handle UART character and string output. 279(UART input is handled by an ISR.) There are two string output 280functions, \c printstr() and \c printstr_p(). The latter function 281fetches the string from \ref avr_pgmspace "program memory". Both 282functions translate a newline character into a carriage return/newline 283sequence, so a simple \c \\n can be used in the source 284code. 285 286The function \c set_pwm() propagates the new PWM value to the PWM, 287performing range checking. When the value has been changed, the new 288percentage will be announced on the serial link. The current value is 289mirrored in the variable \c pwm so others can use it in calculations. 290In order to allow for a simple calculation of a percentage value 291without requiring floating-point mathematics, the maximal value of the 292PWM is restricted to 1000 rather than 1023, so a simple division by 10 293can be used. Due to the nature of the human eye, the difference in 294LED brightness between 1000 and 1023 is not noticable anyway. 295 296\subsection largedemo_code_p5 Part 5: main() 297 298At the start of \c main(), a variable \c mode is declared to keep the 299current mode of operation. An enumeration is used to improve the 300readability. By default, the compiler would allocate a variable of 301type \e int for an enumeration. The \e packed attribute declarator 302instructs the compiler to use the smallest possible integer type 303(which would be an 8-bit type here). 304 305After some initialization actions, the application's main loop 306follows. In an embedded application, this is normally an infinite 307loop as there is nothing an application could "exit" into anyway. 308 309At the beginning of the loop, the watchdog timer will be retriggered. 310If that timer is not triggered for about 2 seconds, it will issue a 311hardware reset. Care needs to be taken that no code path blocks 312longer than this, or it needs to frequently perform watchdog resets of 313its own. An example of such a code path would be the string IO 314functions: for an overly large string to print (about 2000 characters 315at 9600 Bd), they might block for too long. 316 317The loop itself then acts on the interrupt indication bitfields as 318appropriate, and will eventually put the CPU on sleep at its end to 319conserve power. 320 321The first interrupt bit that is handled is the (software) timer, at a 322frequency of approximately 100 Hz. The \c CLOCKOUT pin will be 323toggled here, so e. g. an oscilloscope can be used on that pin to 324measure the accuracy of our software clock. Then, the LED flasher for 325LED2 ("We are alive"-LED) is built. It will flash that LED for about 32650 ms, and pause it for another 950 ms. Various actions depending on 327the operation mode follow. Finally, the 3-second backup timer is 328implemented that will write the PWM value back to EEPROM once it is 329not changing anymore. 330 331The ADC interrupt will just adjust the PWM value only. 332 333Finally, the UART Rx interrupt will dispatch on the last character 334received from the UART. 335 336All the string literals that are used as informational messages within 337\c main() are placed in \ref avr_pgmspace "program memory" so no SRAM 338needs to be allocated for them. This is done by using the PSTR macro, 339and passing the string to \c printstr_p(). 340 341\section largedemo_src The source code 342 343\htmlonly 344Source file: <a href="../examples/largedemo/largedemo.c">largedemo.c</a> 345\endhtmlonly 346 347\latexonly 348The source code is installed under 349 350\texttt{\$prefix/share/doc/avr-libc/examples/largedemo/largedemo.c}, 351 352where \texttt{\$prefix} is a configuration option. For Unix 353systems, it is usually set to either \texttt{/usr} or 354\texttt{/usr/local}. 355\endlatexonly 356 357*/ 358