% text/plain

 
  % -------------------------------------------
  %  latex generated by: booktolatex.cgi   
  %   from source file : ../htdocs/books/arduino/arduino-book.txt       
  %                  on: 28 March 2024,  3:45pm         
  %         querystring: books/arduino/arduino-book.txt  
  %       document-root: /var/www/html
  %         script-name: /cgi-bin/booktopdf.cgi
  %         Server-name: bumble.sourceforge.net
  %          Sed-script: booktolatex.sed
  % ------------------------------------------- 

  \documentclass[a4paper,12pt]{article} 
  \usepackage[margin=0.4cm,noheadfoot]{geometry} 
  \usepackage{color}                   %% to use colours, use "xcolor" for more
  \usepackage{multicol}                %% for multiple columns 
  \usepackage{keystroke}               %% for keyboard key images 
  \usepackage[toc]{multitoc}           %% for multi column table of contents
  \usepackage{tocloft}                 %% to customize the table of contents
  \setcounter{tocdepth}{2}             %% only display 2 levels in the contents
  \setlength{\cftbeforesecskip}{0cm}   %% make the toc more compact
  \usepackage{listings}                %% for nice code listings
  %\lstset{language={},
  \lstset{language=,                 
    %% define special comment delimiters '##(' and ')' 
    moredelim=[s][\color{grey}\itshape\footnotesize\ttfamily]{~(}{)},
    basicstyle=\ttfamily,           %% fixed pitch font
    xleftmargin=1cm,                %% margin on the left outside the frames
    breaklines=true,                %% break long code lines
    breakatwhitespace=false,        %% break long code lines anywhere
    breakindent=10pt,               %% reduce the indent from 20pt to 10
    postbreak=\mbox{{\color{blue}\small$\Rightarrow$\space}},  %% mark with arrow
    showstringspaces=false,            %% dont show spaces within strings 
    framerule=5pt,                     %% thickness of the frames
    rulecolor=\color{lightgrey}, frame=l}   %% source code settings
  \usepackage{graphicx}                %% to include images
  \usepackage{fancybox}                %% boxes with rounded corners 
  \usepackage{wrapfig}                 %% flow text around tables, images 
  \usepackage{tabularx}                %% change width of tables 
  \usepackage[table]{xcolor}           %% alternate row colour tables
  \usepackage{booktabs}                %% for heavier rules in tables 
  \usepackage[small,compact]{titlesec} %% sections more compact, less space
  \usepackage{enumitem}                %% more compact and better lists 
  \setlist{noitemsep}                  %% reduce list item spacing 
  \usepackage{hyperref}     %% make urls into hyperlinks
  \hypersetup{              %% add "pdftex," if only pdf output is required
     colorlinks=true,       %% set up the colours for the hyperlinks 
     linkcolor=black,       %% internal document links black 
     urlcolor=black,        %% url links black 
     filecolor=red,       
     citecolor=red, 
     bookmarks=true, pdfpagemode=UseOutlines} 

  % define some colours to use
  \definecolor{lightgrey}{gray}{0.70}
  \definecolor{grey}{gray}{0.30}

  \titleformat{\section}[frame]    %% titlesec: create framed section headings
     {\normalfont} 
     {\filleft \footnotesize \enspace Section \thesection\enspace\enspace} 
     {3pt} {\bfseries\itshape\filright} 
     
  \title{} 
  \author{}
  \date{28 May 2021,  3:53am} 
  \setlength{\parindent}{0pt}
  % \setlength{\parskip}{1ex}

  % label lists with stars
  \renewcommand{\labelitemi}{$\star$}

  \begin{document} 

  \centerline{\Large \bf } \medskip
  \begin{center}
    {\huge ``}\textit{}{\huge ''}
    \textsc{}
  \end{center}
  % -----------------------------------
  % the toc should be 2 columns because of the \multitoc package 
  \tableofcontents


\emph{ * Arduino and Avr programming using mainly Assembler }

  This booklet contains information about my experiments with the arduino
  boards, such as ``duemilenove'', ``pro mini'', ``eleven'', ``uno''. These 
  boards often use the avr atmega328P microcontroller, which is an 8bit
  harvard architecture uC.
  
  Its purpose is to investigate the avr architecture from an assembly
  programming and c language perpective.

  Generally my interest is often focussed on coding rather than hardware, or
  circuit design or robotics or what-not.  So I am largely content to
  experiment over a serial connection.

\section{Setup}
  
\emph{ Install arduino ide }
\begin{lstlisting}
  apt-get install arduino
\end{lstlisting}

  Arduino has to be run as sudo on my computer!! to be able to edit
  sketches. eg sudo arduino

\emph{ Install avrdude and avra to compile , upload from command line. (not ide) }
\begin{lstlisting}
  apt-get install avrdude avra
\end{lstlisting}
 
\emph{ Install fritzing to make pretty pictures of arduino circuits }
\begin{lstlisting}
  apt-get install fritzing
\end{lstlisting}

  Connect usb to uart connector..
     rx:tx tx:rx gnd:gnd 3v3:vcc dtr:dtr 
     dont connect 5v (for a 3v3 pro mini for example)

  In the ide choose tools-$>$board-$>$pro mini 328 3v3  (for example)
  choose serial port (usb for example)
  Load an example sketch from ide, eg ``blink'' and upload.
  what led on pin 13 blink.

\emph{ Install arduino-mk for command line stuff with arduino }

\emph{ Environment vars for mk }
  -------
    ARDUINO\_DIR   = /usr/share/arduino
    ARDMK\_DIR     = /usr
    AVR\_TOOLS\_DIR = /usr
  ,,,

\emph{ Make file for arduino-mk }
  -------
    BOARD\_TAG    = pro328     \# for the pro mini 3v3 atmega328
     ARDUINO\_PORT = /dev/cu.usb*
    ARDUINO\_PORT = /dev/ttyUSB0
     include libraries here
    ARDUINO\_LIBS = Ethernet Ethernet/utility SPI
    include /usr/share/arduino/Arduino.mk

  ,,,

\emph{ Show valid values for the boardtag variable. }
\begin{lstlisting}
  make show_boards
\end{lstlisting}

  http://www.mjoldfield.com/atelier/2009/02/arduino-cli.html
    info on how to do it.

  make sketch file, eg ``first.ino'' and copy to new dir, cd there

\begin{lstlisting}
  make
\end{lstlisting}

\emph{ Upload sketch }
\begin{lstlisting}
  make upload
\end{lstlisting}

  It worked!!!

\subsection{Mac Osx Setup}

\emph{ Install command line utilities on mac osx }
\begin{lstlisting}
  brew install avra avrdude picocom
\end{lstlisting}

  Avra does not seem to allow anything on the same line as a 
  label in mac osx. This may be a bug. ``abort trap: 6'' error message

\section{The Simplest Program}

  I think the simplest possible working code example on an arduino
  board is to just turn on the on-board led (at portb bit 5). 
  At the very least this can be used to indicate some boolean 
  result (true/false, 0/1 etc). The advantage of this is that no extra
  hardware is required to run the code.

\emph{ Turn on the on-board led (at pin 13 or portb,5) on an arduino board }
  -------
    .include ``m328Pdef.inc''
    sbi DDRB, 5   ; set the data direction to output of bit 5 on PORTB
    sbi portb, 5  ; turn on the output pin  
  ,,,,

\emph{ Turn off the on-board led on an arduino board }
  -------
  .include ``m328Pdef.inc''
    sbi DDRB, 5    
    cbi portb, 5  ; turn off the output pin 
  ,,,,

\emph{ The same code as above but with a better framework  }
  -------
  .nolist
  .include ``m328Pdef.inc''
  .list
  .dseg
    ; create data buffers here in sram
  .cseg
    .org 0
    jmp start
    ; put interrupt service routine vectors here. 
    ; maybe create flash memory buffers here, or functions, or else put
    ; them at the end of the code. which maybe better because they dont
    ; get in the way of the ISR vector jumps.
  start:
    sbi DDRB, 5   ; set the data direction to output of bit 5 on PORTB
    sbi portb, 5  ; turn on the output pin  
    halt:
      rjmp halt
  ,,,,

\section{Sketches}

  Programs written in the arduino ide are called sketches and are 
  written in a modified version of the c language. This is much simpler 
  than using avr assembly, especially because of the numerous libraries
  available to drive devices (servos, etc) and read sensors. But I like 
  assembly because it allows me to think about language and minimalism.

\emph{ Basic sketch with serial  }
  \begin{lstlisting}
   void setup() {
     Serial.begin(9600);  
     Serial.println("Hello !!!"); 
   }

   void loop() {
   }
  \end{lstlisting}
                   
\subsection{Blink}

  Blink is the quintessential starting sketch on the arduino.
  It requires no hardware because all or most arduinos have a 
  LED on the board.

\emph{ Blink the onboard led  }
  \begin{lstlisting}
   // on some arduino boards the on-board led may be 
   // on a different pin.

   int led = 13;
   int milli = 200;

   void setup() {
     pinMode(led, OUTPUT);     
   }
   void loop() {
     digitalWrite(led, HIGH);   // turn LED on 
     delay(milli);              // wait some milliseconds
     digitalWrite(led, LOW);    // turn LED off 
     delay(milli);              // wait
   }
  \end{lstlisting}

\section{Boards}

  pro mini - based on atmega328. connect with ftdi cable to usb
    32K flash (program) - 2K bootload
    2K sram (data). 1K eeprom
    3.3v and 8 megaherz
    5v and 16 megaherz
    External interrupts. pin 2,3

  uno - atmega328, 5v 16megaherz? 

\section{Books}

  The mazidi book looks a good and simple resource for 
  programming the arduino in assembler. But the examples must 
  be modified for the atmega328

  http://www.microdigitaled.com/AVR/Code/AVR\_codes.htm
    all the mazidi books examples as plain text source code are
    available here which is an amazing resource. Since all the 
    examples are very carefully and well written. 
  
\emph{ Wget -c --user-agent=Mozilla --no-directories --accept='Example*.*' -r -l 1 http://www.microdigitaled.com/AVR/Code/AVR\_codes.htm }
    This wget got most of the chapters but not all.
    -c continue, -r -l1 recursive but only one level, --accept file name 
      pattern.
    
   The examples need to be adapted because they are for the m32def device
   eg txen -$>$ txen0, ucsrb -$>$ ucsr0b. Also, many ``out'' instructions
   need to be replaced by ``sts'' since we are dealing with extended i/o
   space. I think

   The examples are all uppercase and use tabs between mnemonics
   and register names.
   
\emph{ Make names better }
\begin{lstlisting}
  rename 's/\.TXT$/.txt/' *.TXT
\end{lstlisting}

\emph{ Insert an example using vim }
\begin{lstlisting}
  :r mazidi/Example11_5.asm
\end{lstlisting}

\subsection{Arduino C Books}
  
   "Arduino, circuits and projects guide" by Gunter Spanner
   has lots of good stuff in it. Eg sin wave fast pwm for nice 
   ``ding'' tones etc.

\section{Goals}

  To learn how to call code using indirect addressing
  (ie using the x, y, z registers) so we can do something like
\begin{lstlisting}
  call bx  ; x86 architecture
\end{lstlisting}

  To develop a simple repl loop, ``read, evaluate, print, loop'' 
  So a simple read-only forth style interface over a serial 
  connection- what used to be known as a Forth ``Home Brew''
  
  play chess on an atmega328 microcontroller over a serial connection.

  Develop a byte code system. Ie, a simple interpreter of byte 
  code for the atmega328

  
\section{Tools}


  \arrayrulecolor{gray}
  \begin{center}
  \begin{tabular}{ |rl| }
    \multicolumn{2}{c}{\textbf{ tools }} \\
  \hline

 \texttt{ avra } & An assembler to use with arduino \\ 

 \texttt{ avrdude } & A tool to program the arduino board \\ 

    \hline
    \end{tabular}
    \end{center}
\section{Buttons}

  We can connect a button to provide some input to the microcontroller.
  We either use an internal pull-up/down resistor or an external one

  not working!! light always on...

\emph{ Turn on the on-board led when a button is pressed  }
  \begin{lstlisting}
  /* The circuit:
   * LED attached from pin 13 to ground 
   * pushbutton attached to pin 2 from +3v3 
   * 10K resistor attached to pin 2 from ground or internal pullup
    */  
      const int buttonPin = 2;   
      const int ledPin =  13;   
      int buttonState = 0;   

      void setup() {
        pinMode(13, OUTPUT);      
        // dispense with external resistor
        pinMode(buttonPin, INPUT_PULLUP);     
      }

      void loop(){
        buttonState = digitalRead(buttonPin);
        if (buttonState == HIGH) {     
          // turn LED on:    
          digitalWrite(13, LOW);  
        } 
        else {
          // turn LED off:
          digitalWrite(13, HIGH); 
        }
      }

  ,,,,

DISPLAYS 

SEVEN SEGMENT DISPLAY ....

  This is the old calculator number display. 
  
NOKIA SCREEN ....

  nokia 5510, based on phillips pd.... is commonly used with 
  arduino. runs on 3v3 so its easiest to use it with a 3v3 pro mini
  arduino. Otherwise, voltage dividers/ level shifters are needed 
  for power and for all digital pins...
  
LCD ....

  Hitachi HD44780 is the most common control chip of liquid crystal 
  displays, and is supported by an arduino library.

  The arduino-mk program has a good example of using an lcd with
  and arduino and the lcd library.
  >> /usr/share/doc/arduino-mk/examples/HelloWorld/HelloWorld.ino

  The circuit:

      * LCD RS pin to digital pin 12
      * LCD Enable pin to digital pin 11
      * LCD D4 pin to digital pin 5
      * LCD D5 pin to digital pin 4
      * LCD D6 pin to digital pin 3
      * LCD D7 pin to digital pin 2
      * LCD R/W pin to ground
      * 10K resistor:
      * ends to +5V and ground
      * wiper to LCD VO pin (pin 3)

OLED SCREEN ....

  The Oled screen is a more recent technology compared to lcd screens
  with high contrast and 2 wire interface.

ULTRASONIC 

  Simple ultrasonic boards can find range based on the speed of 
  sound. Ultrasonic Sensor HC-SR04. This needs 5v.
  
  Emit at 40KHz and receive an echo. Speed is dependant on temperature
  of air.

  connections: trigger -> pin 9, echo -> 10, gnd:gnd, vcc:5v I used the 5 volt
  wire from the ftdi board to power the ultrasonic sensor with a pro mini 3v3
  and it worked, but this fried the promini 3v3 after leaving it running
  for a while

  * simple sketch, assuming speed of sound 340 m/s, no resistors
  \begin{lstlisting}
  // pin numbers or use "define"
  const int trigPin = 9;
  const int echoPin = 10;
  const int ledPin = 13;

  long duration;
  int distance;

  void setup() {
    pinMode(trigPin, OUTPUT); // trigger fires sound pulse
    pinMode(echoPin, INPUT);  // echo receives sound pulse 
    Serial.begin(9600);       // Starts the serial communication
  }

  void loop() {
    digitalWrite(trigPin, LOW);
    delayMicroseconds(2);

    // trigger HIGH for 10 micro secs sends sound pulse
    digitalWrite(trigPin, HIGH);
    delayMicroseconds(10);
    digitalWrite(trigPin, LOW);

    // returns the sound wave travel time in microseconds
    duration = pulseIn(echoPin, HIGH);

    // distance in centimeters, assumes speed of sound 340 m/s
    distance = duration*0.034/2;
    Serial.print("Echo duration: ");
    Serial.print(duration);
    Serial.println(" microseconds ");
    Serial.print("Distance: ");
    Serial.print(distance);
    Serial.println(" cm ");
    if (distance < 40) {
      digitalWrite(ledPin, HIGH);
      Serial.println("< 40 cm !!");
    } else {
      digitalWrite(ledPin, LOW);
    }
    delay(800);
  }

  \end{lstlisting}
  
\section{Brushless Motors And Esc}

  Brushless motors with an ``esc'' unit are driven in exactly the same way
  as servo motors, that is, with a 50 herz wave, with a pulse width
  varying between roughly 1ms and 2 ms. At 50 hz the wave length will be 20ms.

  Brushless motors and electronic speed control units are used on many remoted 
  control model aircraft. This means that the propeller can be easily controlled
  with an arduino.

\section{Stepper Motors}

  Use phase correct pwm mode for stepper motors.

\section{Servo Motors}

  https://sites.google.com/site/qeewiki/books/avr-guide/timers-on-the-atmega328
    Good atmega info. Also has a hint on motors.

  Servo motors should be driven with pwm at a frequency of 50Hz.
  
  Not sure yet whether Servo motors need a phase correct PWM or not...

  You can also use pulse width modulation to control the angle of a servo
  motor attached to something mechanical like a robot arm. Servos have a shaft
  that turns to specific position based on its control line. Our servo motors
  have a range of about 180 degrees.

  Comment from ``sparkfun'' site:
    "Frequency/period are specific to controlling a specific servo. A typical
    servo motor expects to be updated every 20 ms with a pulse between 1 ms
    and 2 ms, or in other words, between a 5 and 10\% duty cycle on a 50 Hz
    waveform.  With a 1.5 ms pulse, the servo motor will be at the natural 90
    degree position. With a 1 ms pulse, the servo will be at the 0 degree
    position, and with a 2 ms pulse, the servo will be at 180 degrees. You can
    obtain the full range of motion by updating the servo with an value in
    between."

  The text above gives hints how to control a servo with avr assembly
  and pwm.

\subsection{Driving Multiple Servo Motors}

  Is is possible to drive 2 or 3 servos with timer1, not sure about timers
  0 and 2. The other alternative is 'bit banging'.

\emph{ A comment }
  -------

  First note that in OCRxn, the x defines the Timer number and n defines which
  servo you are controlling. Most timers can control multiply servos. For
  example on Timer1 you can set OCR1A, OCR1B, and sometimes OCR1C (read the
  data sheet to find out how many servos a particular timer can support).

  ,,,

  The ``servo'' c library available for arduino is capable of driving multiple (12)
  servos at once.

  For doing the same thing in avr assembly language here is some advice from
  Chuck Baird on the avrfreaks.net site:

  "... driving only 6 servos is fairly simple. You need to put out a pulse to
  each servo every 20 ms, and the pulse width (which determines the servo's
  position) is a maximum of 2 ms wide. Therefore, use a timer to generate an
  interrupt every 20/6 ms, and on each interrupt attend to one servo, round
  robin.  In the ISR, turn the bit for the ``current'' servo on, then start a
  second timer for up to 2 ms (depending on that servo's position). When that
  interrupt fires, turn that same bit off.  And that's one (easy) way to do it,
  if you have 2 timers to spare."

  The above comment provides a template for driving multiple servo motors
  in avr assembly language

\section{Servo Motors In C}

  The arduino libraries include the servo library which can drive many
  servo motors at once, which is very convenient.

  positions ??
  
  45: extreme left
  90: centre
  135: extreme right

  tested on freetronics ``uno'' and promini 3v3
  circuit: 3v3: red wire, gnd: black wire, other to pin 9, no resistor

\emph{ Control a servo motor }
  \begin{lstlisting}
    #include <Servo.h>

    Servo servo;
    //int pos = 0;

    void setup() {
      Serial.begin(9600);
      servo.attach(9);
    }
    void loop() {
      Serial.println("sweep...");
      for (int pos = 0; pos <= 180; pos += 1) { 
        servo.write(pos); 
        delay(15);  
      }
      Serial.println("and back...");
      for (int pos = 180; pos >= 0; pos -= 1) { 
        servo.write(pos);  
        delay(15); 
      }
    }
  \end{lstlisting}

  We can communicate to the program below with ...
\begin{lstlisting}
  sudo picocom -b 9600 --echo /dev/ttyUSB0
\end{lstlisting}

  There is a gotcha here. Many serial terminals send line feeds
  cr lf etc which makes Serial.available return true
  even when there is nothing to read. So I am using a hack
  in the code below to get rid of the lf if any.

\emph{ Control a servo motor with the keyboard and a serial connection }
  \begin{lstlisting}
   #include <Servo.h>
   Servo servo;
   int v = 0;
   
   void setup() {
     pinMode(9,OUTPUT);
     servo.attach(9); //analog pin 0
     //servo.setMaximumPulse(2000);
     //servo.setMinimumPulse(700);
     Serial.begin(9600);
     Serial.println("Enter position 0 to 180 ?");
   }
   
   void loop() {
     //static int v = 0;
     if (Serial.available()) {
       int v = Serial.parseInt();
       servo.write(v);
       Serial.print("To position:");
       Serial.println(v);
       v = 0;
       // get rid of line feed if terminal is sending one
       // this is not working... maybe need to disable in terminal 
       // software.
       if (Serial.available()) { Serial.read(); }
       if (Serial.available()) { Serial.read(); }
     }
   }
  \end{lstlisting}


BLUETOOTH WITH HC05 

  The HC-05 is a very inexpensive and widely used bluetooth 
  chip which is compatible and easy to use from an Arduino board
  The default baud rate is 38400 (not 9600), 8 data bits, 1 stop bit,
  no parity bit. 
  
  Once the hc05 is connected to the rx and tx pins of
  an arduino board, the serial communication coding is exactly the 
  same as any other serial connection, which is very handy.

  https://www.itead.cc/wiki/Serial\_Port\_Bluetooth\_Module\_\%28Master/Slave\%29\_:\_HC-05     Lots of good info about the HC=05 

  http://www.instructables.com/id/Modify-The-HC-05-Bluetooth-Module-Defaults-Using-A/
     Modify hc05 with at commands

  The hc-05 has an onboard led which is good for knowing what is
  going on with it. So ...


  \arrayrulecolor{gray}
  \begin{center}
  \begin{tabular}{ |rl| }
    \multicolumn{2}{c}{\textbf{ hc-05 onboard led information }} \\
  \hline
    led not lit: no power! put 3v3 on vcc and gnd to gnd 
    led fast flash: power but no signal
    led slow single flash: connected to serial but not paired
    led slow double flash: connected and paired!!

    \hline
    \end{tabular}
    \end{center}
  Using the hc05 bluetooth board we can connect to an arduino
  microcontroller using a linux computer with no wires!!

  http://pi19404.github.io/pyVision/2015/04/03/22/
    this page was very usefull for getting it all working
    and giving command line incantations.

  It is possible blueman does this for you, below

\emph{ In /etc/bluetooth/rfcomm.conf put, changing the mac address }
  \begin{lstlisting}
    rfcomm0 {
      bind no;
      device 98:D3:31:XX:XX:XX;  # change this to your HC05 mac address
      channel 1;
      comment "Serial Port";
    }
  \end{lstlisting}


\emph{ Install cutecom a nice gui serial terminal }
\begin{lstlisting}
  sudo apt-get install cutecom
\end{lstlisting}

 Now pair the device using 'blueman', your device should appear
 with an option to connect via serial

\emph{ Start the cutecom serial terminal }
\begin{lstlisting}
  sudo cutecom
\end{lstlisting}
 
 Note!! On my system cutecom has to be started as root or you
 wont be able to connect to open /dev/rfcomm0

 and in the device box type /dev/rfcomm0 (etc). Set
 the baud rate to 57600, and click open device. Now type your
 commands and see the robot move (if its a robot you are controlling).
 Of course this assumes you have code on the arduino that receives
 serial data and executes commands.
 
 Baud Rate: in my experiments the robot moved even when the baud rate
 was not correct (??). 

\emph{ Or use picocom with hc-05 connected to usb port }
\begin{lstlisting}
  sudo picocom -b 38400 --echo /dev/ttyUSB0
\end{lstlisting}

 Unusually the default baud rate for HC-05 bluetooth is 38400 when
 connected via usb, but 9600 when connected via bluetooth...

 Type control-a control-x to exit picocom

\emph{ Minicom is another alternative  }
\begin{lstlisting}
  sudo minicom -b 38400 -D /dev/ttyUSB0
\end{lstlisting}

 Then turn off hardware flow control (control-a o) and turn echo on
 Minicom allows scripts which could be useful. Turning hardware flow 
 control off only seems necessary when connected via usb

AT COMMANDS TO CONFIGURE THE HC05 ....

  We can use the venerable old ``AT'' modem commands to configure an HC-05 chip.
  I thought those days were over ...
  
  I use the graphical ``cutecom'' serial monitor with baud=38400,
  line-ending=cr,lf device=/dev/ttyUSB0 (when the HC-05 is plugged into a usb
  port via a usb-to-uart converter).

  It appears that it is not possible to configure an HC-05 via bluetooth
  which makes sense because it would invalidate the security of the device.

  Connect HC-05 to the usb to uart converter board as follows
\begin{lstlisting}
  rx to tx, tx:rx, 3v3 to vcc, gnd to gnd, easy...
\end{lstlisting}

  The CR+LF line ending is important, it wont work otherwise

  When connecting the HC-05, hold down the little reset button (which it
  hopefully has, otherwise proceedure is different). The led will
  blink very slowly

  Type ``AT'' to receive ``OK'' for confirmation of communication
  
\emph{ See if communication is happening with HC-05 bluetooth chip }
\begin{lstlisting}
  AT
\end{lstlisting}

\emph{ Display the module working state }
\begin{lstlisting}
  AT+STATE?  
\end{lstlisting}
  (eg: ``INITIALIZED'' ``READY'' ``PAIRABLE'' ``PAIRED'' ``INQUIRING''
       ``CONNECTING'' ``CONNECTED'' ``DISCONNECTED'' ``NUKNOW'' )

\emph{ Show the bluetooth password or pin code }
\begin{lstlisting}
  AT+PSWD   or AT+PSWD?
\end{lstlisting}

\emph{ Change the bluetooth connection pin code }
\begin{lstlisting}
  AT+PSWD=<password>
\end{lstlisting}

\emph{ Check the current baud rate, stop bit and parity }
\begin{lstlisting}
  AT+UART? 
\end{lstlisting}

\emph{ Set the baud rate to 38400, no stop bit, no parity }
\begin{lstlisting}
  AT+UART=38400,0,0
\end{lstlisting}

\emph{ Set the baud rate to 115200, stop bit, with parity }
\begin{lstlisting}
  AT+UART=115200,1,2
\end{lstlisting}

\emph{ Get the hc-05 bluetooth address (not mac address) }
\begin{lstlisting}
  AT+ADDR?
\end{lstlisting}
  eg: +ADDR:1234:56:abcdef  (NAP: UAP : LAP)

  These addresses are used when binding master (server) and
  slave (client). See the next sub-section for more information.

  Its important to change the name to something memorable, so
  that pairing will be easy. This name is what appears in the 
  blue tooth connection screen (eg for android/linux/windows)

\emph{ Set module name (default hc-05) }
\begin{lstlisting}
  AT+NAME=<Param>       
\end{lstlisting}

\emph{ Get bluetooth device name (address eg: 00:02:72:OD:22:24) }
\begin{lstlisting}
  AT+RNAME? 0002，72，od2224\r\n 
\end{lstlisting}

\emph{ Check connect mode (0=fixed address, 1=any address, 2=slave loop) }
\begin{lstlisting}
  AT+ CMODE? 
\end{lstlisting}

\emph{ Set fixed address 98:D3:31:20:93:CB }
\begin{lstlisting}
  AT+BIND=98d3,31,2093cb
\end{lstlisting}

\subsection{Master Slave}

  In the master slave mode, the HC-05 can automatically connect
  to another HC-05 bluetooth chip. This obviates the need to 
  have to manually connect via bluetooth in order to control
  a robot, for example. The second HC-05 board can be connected
  to computer with a usb-to-uart board (ftdi)

  When I typed at+init the 2 modules bound together. 
  But... there is disagreement about cmode=0/1 which is 
  fixed address mode???

  I had to configure the master HC-05 (which is plugged into
  the usb port of my laptop via a usb-to-uart board) at 38400 baud even
  though the slave (on the arduino robot) is apparently running at 57600. This 
  works! I get coherent responses from the robot serial connection.
  If I set the master at 57600 I get gibberish responses from the robot
  (which indicates a baud mismatch). It seems that when the HC-05 is
  plugged into the usb port via the usb-to-uart converter it always
  runs at 38400 no matter what its configured baud rate is!!!???

  On my HC-05  at+cmode=0 is fixed address and must be used with at+bind
  On my HC-05  at+cmode=1 binds to any address.
   
  The key to all this is the at+init command which actually binds the ``slave''
  hc-05 to the ``master'' hc-05 (which is connected to the computer or some
  other controlling device. When cmode=1 (connect to any device) after
  at+init the hc-05 blinks slowly while it search for another device in range
  and then binds to it. But when cmode=0 and bind=addr the hc-05 connects
  quickly after at+init (2 short flashes)

\emph{ Set an HC-05 to master mode, and bind it to the slave (on the robot) }
  ------
    AT+ORGL            // factory reset
    AT+RMAAD           // clear all paired devices
    AT+UART=38400,0,0  // baud rate, stop, parity
    AT+ROLE=1          // master mode
    AT+CMODE=0         // fixed address connection mode, yes
    (or AT+CMODE=1   connect to any device in transmission range) 
    AT+BIND=98D3,31,3069B0   // address of slave
    AT+INIT 
  ,,,

  The slave usually doesnt have to be configured at all, it appears.

\emph{ Set an HC-05 to slave mode }
\begin{lstlisting}
  AT+ROLE=0
\end{lstlisting}

\subsection{Gotchas}

  If you connect tx-$>$tx and rx-$>$rx Wrong! (hc05 to arduino)
  the hc-05 will pair and connect but not do anything.

  Sometimes picocom will say
\begin{lstlisting}
  FATAL: cannot open /dev/rfcomm5: Device or resource busy  
\end{lstlisting}
  but why??? maybe the device is being used by some other process
  (cutecom ...)
  
  Make sure you are using 
\begin{lstlisting}
  sudo !!!
\end{lstlisting}
\begin{lstlisting}
  sudo minicom or sudo picocom or sudo cutecom
\end{lstlisting}

  Or make sure that you are using the last /device
  Eg if you try /dev/rfcomm3 when blueman has assigned /dev/rfcomm4
  then rfcomm3 will be ``busy''

\section{Stack}


  The avr chips usually have a hardware stack which is 
  used for procedure calls (call, rcall) and can be used by the 
  programmer explicitly with ``push'' and ``pop''. However the 
  stack is 8 bit, obviously, so it is a bit clumsy to use it to
  pass pointers to code or data space.

  The stack pointer registers can (should?) be initialized before using 
  the stack (ie calling a procedure), but this is done automatically on
  chips since about 2006.

\emph{ Initialize the stack, should be done before any ``call/rcall'' }
  \begin{lstlisting}
    .include "m328Pdef.inc"
    ldi r21, high(ramend)        
    out sph, r2             
    ldi r20, low(ramend)
    out spl, r21
    
  \end{lstlisting}


\subsection{Software Stack}
  
  sometimes you need more than one stack, so you can make your own
  using the X and Y registers

\emph{ Initialiase and use an 8bit software stack with X }
  ------
   .nolist
   .include ``m328Pdef.inc''    ; the atmega328p, the usual arduino uC
   .list

    sbi DDRB, 5   ; make the led 13 output 

    ldi xh, high(RAMEND-128)
    ldi xl, low(RAMEND-128)
    ldi r17, 123
    st X+, r17    ; push value in r17 onto stack
    ld r16, -X    ; pop value from stack into r16
    cpi r16, 123
    sbi portb, 5  ; turn on the led 
  ,,,,

\emph{ An avra macro to push a 16 bit value onto a software stack }
  \begin{lstlisting}
  .nolist
  .include "m328Pdef.inc"
  .list

  .macro pushw 
  .message "no parameters specified"
  .endm

  .def a = r16
  .def b = r17
  .def temp = r18

  .macro pushw_16
    st X+, @0
    st X+, @1
  .endm

  ; push a single byte/char onto 16bit stack
  .macro pushb_8
    st X+, @0
    clr temp
    st X+, temp 
  .endm

  .dseg
    stack:
      .byte 128
  .cseg
    pushw [a:b] 

  ,,,,

WINDOWS

  install driver cp2102 to use the usb to uart device.
  Then putty at baud rate 38400 maybe com70

INTERPRETER

  The following is the bare bones code for running an interpreter
  over a serial connection. Here the mcu receives data via serial and
  executes the appropriate command. A more sofisticated system could
  read the serial stream for a whole line and modify commands with parameters
  etc, after that, if/loop/ etc. A tiny command interpreter is what is 
  needed, maybe an adaption of python, forth, lua or tcl

  This is 'arduino' c...

  * a simple interpreting loop getting commands from serial
  \begin{lstlisting}
  void setup() {
    Serial.begin(57600);
    // ...
  }

  void loop() {
    if (Serial.available() > 0) {
      data = Serial.read();
      Serial.print("rx:");
      Serial.print(data);
    }
    if (data == 'a') {
      // execute command for 'a'
    }
    else if (data == 'b') {
    }
    else {}
  }

SYNTAX FOR ARDUINO C

   * print as ascii
   >> Serial.write(a); 
 Many arduino boards use the atmega328 avr chip which
 has 32K of program memory

 * turn on the led on arduino pin 13
 ----

 ;hello.asm
 ;  turns on an LED which is connected to PB5 (digital out 13)

  .include "m328Pdef.inc"

   ldi r16,0b00100000
   out DDRB, r16   ; DDRB == data direction register B
   out PortB, r16  ; send a 'high' to PB5 only
   Start:
     rjmp Start   ; hang in an infinite loop
 \end{lstlisting}

\emph{ Upload this hex file to the arduino (uno ?) with }
\begin{lstlisting}
  avrdude -p m328p -c stk500v1 -b 57600 -P /dev/ttyUSB0 -U flash:w:hello.hex
\end{lstlisting}

 This is not working. The problem is the 'stk500' which may be
 correct for the 'uno' arduino but not for the duemilenovo.
 see below for a working example. The 
 problem seems to be the -c stk500v1 option

\emph{ Also try for arduino uno s etc }
\begin{lstlisting}
  -b 115200 and the port -P /dev/ttyACM0 
\end{lstlisting}

\subsection{Architecture}

  The atmel atmega chips are 8 bit risc processors. They have
  a stack and a register file. Data memory and program memory
  are separate (program memory is stored in flash). 

\section{Forth Ideas}
   
   See also the ``bytecode'' chapter.

   One way to start to build a system using forth ideas is just
   to implement a data stack and 2 words 'key' and 'emit'. once
   we have these 2 words, we can start to test them and then
   add new words.

   There are a number of important forth ideas. In a minimalistic
   system we can implement only a subset of these ideas in order
   to create a usable interactive system. For example, it may not 
   be necessary to allow the definition of new words, or even 
   to have a stack.
  
   Reverse counted name strings allow decompilation of bytecode- 
   because each opcode in the table contains a link to the 
   execution address, not the header address.

   Ideas:
\emph{ Dictionary:  }
        a linked list dictionary containing procedure names 
        and possibly a help string for each procedure
\emph{ Interactive:  }
        Communicate with the user over a serial connection.
        Accept one word, or multiple words, and look up
        the word in the dictionary and executing it. The word
        could be just a fixed number of characters, to make the 
        logic simpler.
\emph{ Stack or stacks:  }
        passing all parameters on the stack, so that the 
        output of a procedure can be the input of another
        (eg KEY EMIT KEY EMIT which gets a character from the 
        keyboard, puts it on the stack. Then ``emit'' takes that 
        value from the stack and displays it on some device. In
        Forth the stack cell size is at least 16bits, but for a 
        minimal system 8bits may be useful)
\emph{ A procedure to display available procedures (eg WORDS) }
\emph{ A procedure to display available procedures and a short }
       help string.
\emph{ Allow numbers to be pushed onto the stack. This is useful because }
       it allows the user to interactively provide parameters for a 
       procedure (eg ``5 blink'' would push 5 onto the stack and then
       call the procedure ``blink'' to flash the on-board led 5 times)

\subsection{Minimalistic System Using Forth Ideas}

  This section will try to implement some or all of the above ideas
     
  warning!: when the compiler puts in extra bytes to make .db sections
  even, this may ...?  break the linked-list dictionary.

  The code below is very useful because it can become a framework for 
  a minimalistic interactive system.

  Also, need to be careful when doing pointer arithmetic and counted 
  strings, because the compiler puts in extra zeros to make all addresses
  even.
  
  Now need to search for a command ``find'' and execute it. compare works
  Once find is working we have a useful interactive 8bit system.
  We then write a loop using ``get then find''. Then we can think about 
  parsing multiple commands (words). Then think about getting numbers
  on the stack.
  
  For a limited system, no command help will be available, so the struct should 
  be 

\emph{ Structure of header with help string }
  ---
    commands:
      .db ``help for this command/word'', 0
      .dw commands 
    commandh:
      .dw backlink ; pointer to prev header ``nameh''
      .db 5, ``command''
    command:
      etc
  ,,,

  If no help is in the dict, the the .dw commands link will be zero.
  The ``help'' word can check for zero. This means that we can run a 
  preprocessor to remove help strings where memory is very limited.
  The ``type'' command will also check for zero and terminate printing.

  I would like to convert the system below to using a 16bit software
  data stack using eg X or Y as the top-of-stack pointer. This stack will grow
  towards high memory (and towards the return stack). 
  This means that we dont have to juggle data on the atmega hardware stack
  
  Its useful to have some commands/words which just do
  the same thing as another. 

  Another idea: A name dictionary, that contains pointers to 
  all the wordlists. This allows namespaces.

\emph{ Structure of an alias  }
  ---
    ; no help header
    somecommand:
      .dw prevword ; pointer to prev header
      .db `` command'', 8  ; notice the 1st char is a space
    somecommandx:
      .dw linktounalias
  ,,,

\emph{ Some forth ideas implemented, using a software data stack }
  --------
   .ifdef 0
      This version uses a software 16bit datastack with X as pointer

      with a procedure header with name and
      help string. will try to search for a procedure name and 
      execute, can print command names and help 

      Modify to use a software datastack, using X reg as the 
      top of stack pointer. This should make parameter passing easier
      (no juggling) and also allows proceedures to be used as opcodes
      in a bytecode system. Also, change the help header struct
      as above. 

      In the code below, for avra, all the macro parameters, must 
      have [] around them.
     
      The code is working upto ``words''. need to write ``help'', compare, find
      etc to have a simple working system. also can add a bytecode table.
      
\emph{ The line below can be used to preprocess the code to remove  }
        the help string from each word, thus reducing the size of the program
        greatly
\begin{lstlisting}
  sed '/h:$/,/n:$/{/\.db/d;/\.dw/s/\.dw.*/.dw 0/}' test.asm
\end{lstlisting}

      10 may 2020: 1134 bytes with help strings, 838 bytes with no help

      Bug on macosx with avra (got via brew install)
        ldi XH, high(stack)
        ldi XL, low(stack)
        st X, r16 
        ld r16, X
      This corrupts the data in r16 because the X pointer is not valid.
      This is because of how the ``stack'' label in the dseg is compiled.
      using ``high(RAMEND-128)'' etc works instead.
      
      But better is put .org 0 at the top of dseg. This seems to solve the
      problem.
   
      15 may 2020 
        size: 2118 bytes
        work to do: 
          get a number on the stack, 
          allow multiple commands in ``interpret''
          allow search the help strings
          a welcome message with stats (system size, number of words etc)
          respond to ``hi'' and hello.
          
        words I would like now, $>$in nextword (parse/word), ``contains''
        to see if a word contains a substring.

        This was, will be developed in the following order. This is a 
        useful order for bringing up a system on new hardware because it
        allows the code to be tested as it is created.
          emit, key, dup, get/accept, words, help, .hexchar, .hex,
          .stack, compare, find, interpret.
     
      14 may 2020
        wrote ``find'' and ``do''/execute/perform. Fixed ``do'' by 
        dividing the execution pointer by 2.

      13 may 2020
        this is now outgrowing the book format. needs to become
        a separate app. Find is working but ``do''/perform/execute
        not yet. need to make a ``nextword'' command which scans the input
        buffer for the next word (like ``parse'' or ``word'' in forth) and
        an ``in'' input pointer.
        Also, make an input buffer history, so that up arrow recalls 
        a command. Also, make a ``keycode'' word, that shows keycodes
        for words.

      12 may 2020
        wrote .stack (hex), put a namelist dictionary in
        code now 1728 bytes, but a lot of that is help strings
        next tasks, make sure compare works, then write ``find''
        and ``do'' which executes the address on the stack.

   .endif

   .nolist
   .include ``m328Pdef.inc''    ; the atmega328p, the usual arduino uC
   .list

   ; opcode numbers as used in the opcode table. These are not currently
   ; used here but included to show how this system is compatible with
   ; a byte code virtual machine.
   .equ DUPx = 1 
   .equ DROPx = DUPx+1 
   .equ BSWAPx = DROPx+1  ; bswap - swap bytes in top stack item
   .equ EMITx = BSWAPx+1 
   .equ KEYx = EMITx+1 
   .equ STARx = KEYx+1 

   .def temp = r20       ; short term calculations 
   .def templ = r21      ; 16bit temporary values 
   .def temph = r22      ; 
   .def counter = r16    ; counter loops etc
   .def flag = r17       ; true false etc 
   .def param = r24      ; used for local parameters
   .def zero = r0        ; just contains zero 

   ; these macros should make the code more readable when 
   ; pushing and popping onto/from the software stack

   .macro pushw 
   .message ``no parameters specified''
   .endm

   .macro pushw\_16
     st X+, @1     ; push the low byte first
     st X+, @0
   .endm

   .macro pushb 
   .message ``no parameters specified''
   .endm

   ; push a single byte/char onto 16bit stack
   .macro pushb\_8
     st X+, @0
     st X+, zero  ; push zero as the high byte
   .endm

   .macro pushc
   .message ``no parameters specified''
   .endm

   ; push an immediate 8bit char value
   ; use with ``pushc '*'''
   .macro pushc\_i
     ldi temp, @0
     st X+, temp 
     st X+, zero  ; push zero as the high byte
   .endm

   .macro popb 
   .message ``no parameters specified''
   .endm

   ; pop a single char/byte from the software stack 
   .macro popb\_8
     ld @0, -X    ; discard top byte
     ld @0, -X
   .endm

   .macro popw
   .message ``no parameters specified''
   .endm

   ; pop a 16bit value from the stack 
   ; could make this safer by checking for stack underflow
   .macro popw\_16
     ;sbiw XH:XL, 0    ; check for stack underflow
     ;breq underflow 
     ld @0, -X    ; high byte 
     ld @1, -X
   .endm

   .dseg       
   .org 0x100
     ; a buffer for typed commands
     input:
      .byte 32
     stack:     ; a 64 cell 16bit data stack
      .byte 128

   .cseg        ; rom program memory (flash)
   .org 0
   rjmp start

   start:
     ; assume auto initialisation of stack
     ; set up X as a software data stack pointer 
     ldi xh, high(stack)  
     ldi xl, low(stack)    
     rcall serial
     clr zero       ; keep zero register=0

   here: 
     rcall interpret
   halt:
     rjmp halt

   code:
     ; some bytecode. need to write an ``execute'' procedure 
     ; to test this. zero exits from the proc
     .db KEYx, EMITx, KEYx, EMITx, KEYx, EMITx, 0, 0

   ; pointers to opcode functions. 
   optable:
     .dw 0, dup, drop, bswap, emit, key
   
   data: 
     .db 6, ``ABCabc''
   test: 
     .db ``testing typing and counting'',0

   ; initialize an rs232 serial connection using onboard usart
   ; no header because it cant be used interactively.
   serial:
     ldi r16, 1$<$$<$TXEN0 | 1$<$$<$RXEN0     ; enable transmit receive 
     sts UCSR0B, r16       
     ldi r16, 1$<$$<$UCSZ01 | 1$<$$<$UCSZ00
     sts UCSR0C, r16      
     ldi r16, 0x66    ; the baud rate, 9600 on 16 megaherz chip
     sts UBRR0L, r16
     ldi r16, 0x00    ; the baud rate, 9600
     sts UBRR0H, r16
     ret
   
   ;---------
   ; This is a dictionary of namespaces 
   ; if we have a lot of words/commands in the system we can 
   ; divide them up into namespaces.
   namelisth:
    .db ``a list of namespaces.'', 0
    .dw namelisth
   namelistn:
    .dw 0    ; this is the first namespace, so no backlink
    .db ``namelist'', 8, 0  
   namelistp:
    .dw 0    ; a pointer to last name in this list 

   corelisth:
    .db "standard forthish words like pop, push etc.", 0
    .dw corelisth
   corelistn:
    .dw namelistp   ; this is the first namespace, so no backlink
    .db ``corelist'', 8, 0  
   corelistp:
    .dw last        ; a pointer to last word in the standard dict

   ; end of the namespace dictionary
   ;-----------------
   
   ; duplicate the top (16bit) stack item
   duph:
    .db "op: duplicate top item of stack (n - n n)",0    ; help string
    .dw duph
   dupn:
    .dw 0         ; 1st procedure, so no backlink
    .db ``dup'',3   ; reverse counts for bytecode decompilation 
   dup:
     popw [temph:templ]
     ;adiw XH:XL, 2       ; adjust stack pointer
     pushw [temph:templ]
     pushw [temph:templ]
     ret

   droph:
    .db "op: drop top item of stack ( n - )",0   
    .dw droph
   dropn:
    .dw dup         ; 1st procedure, so no backlink
    .db ``drop'',4,0  ; reverse count
   drop:
     sbiw XH:XL, 2    ; adjust stack pointer
     ; or popw [temph:templ]
     ret

   bswaph:
    .db "op: swap bytes in top stack item (n - m)",0   
    .dw bswaph
   bswapn:
    .dw drop       
    .db ``bswap'',5
   bswap:
     ld temph, -X 
     ld templ, -X 
     st X+, temph
     st X+, templ
     ret

   keyh:
    .db "op: receive one character from keyboard ( - c)",0    ; help string
    .dw keyh
   keyn:
    .dw bswap    ; back-link in linked-list dict to execution address
    .db ``key'',3    
   key:
   wait:
     lds temp, UCSR0A   ; get usart status info
     sbrs temp, RXC0    ; has a byte been received?
     rjmp wait          ; if not just wait for one.
     lds temp, udr0     ; get received byte
     ; push the char onto the stack, high byte zero
     pushb [temp]
     ret

   keycodeh:
    .db "show keycodes for keys pressed. 'q' to quit. ( - )",0    ; help string
    .dw keycodeh
   keycoden:
    .dw key    ; prev word 
    .db ``keycode'',7    
   keycode:
     ; print the help for this word
     ldi ZH, high(keycodeh$<$$<$1)
     ldi ZL, low(keycodeh$<$$<$1)
     pushw [ZH:ZL]
     pushc [200]     ; type until 0
     pushc [0]       ; type rom not ram
     rcall type
     rcall newline
   kcagain:
     pushc ['$>$']
     rcall emit
     rcall key
     pushc [' ']
     rcall emit
     rcall dothex
     rcall newline
     rjmp kcagain
     ret

   ; using the stack to pass parameters is like a protocol
   ; transmit 1 character from the stack over serial connection
   ; here is the header for the procedure
   emith:
    .db "print 8bit character on top of stack ( c - )",0    ; help string
    .dw emith
   emitn:
    .dw keycode      ; a link to previous word
    .db ``emit'',4,0   ; procedure name with count
   emit:
   transmit:

     lds temp, UCSR0A ; usart control, status register
     sbrs temp, UDRE0 ; is UDR empty?
     rjmp transmit    ; if not, then just wait (block)
     ;ld temp, -X     ; discard high byte (zero)
     ;ld temp, -X     ; char to print 
     popb [temp]
     sts UDR0, temp  ; if usart buffer empty tx character
     ret   

   ; note! reverse name counts allow decompilation of bytecode!
   ; this also has a flag variable for ram/rom
   ; stack: address+1 count rom/ram-flag
   counth:
    .db "put count on stack, increments pointer (A flag - A+1 c flag) ",0
    .dw counth
   countn:
    .dw emit        ; backlink
    .db ``count'',5    ; counted name 
   count:
     popb [flag]  ; rom or ram
     popw [ZH:ZL] ; pointer to counted string
     cpi flag, 0       ; check if rom or sram to print
     breq countrom     ; 0=rom, non-zero=sram
     ld temp, Z+       ; get the count
     rjmp countagain 
   countrom:
     lpm temp, Z+      ; get the count
   countagain:
     pushw [ZH:ZL]  ; push new pointer
     pushb [temp]   ; push count 0-255, high byte zero
     pushb [flag]   ; the rom/ram flag (also used by type)
     ret    

   ; type has a pointer and count on the stack 
   ; this also terminates printing if a zero byte is found.
   ; needs to have a parameter for sram and rom because different
   ; instructions are used ``lpm'' and ``ld''. Put a flag on the stack for this.
   ; stack: (rom/sram-address count flag - )
   typeh:
    .db ``print a counted string '',0    ; help string
    .dw typeh
   typen:
    .dw count       ; backlink
    .db ``type'',4,0   ; counted name 
   type:
     popb [flag]       ; boolean flag for sram/rom memory
     popb [counter]    ; how many chars to print
     popw [ZH:ZL]      ; pointer to string
     cpi counter, 0    ; if count is zero, exit
     breq endtype
   nextchar:
     cpi flag, 0       ; check if rom or sram to print
     breq typerom      ; 0=rom, non-zero=sram
     ld temp, Z+
     rjmp continue
   typerom:
     lpm temp, Z+      ; get next character
   continue:
     ; here check for zero and terminate (so prints "c" style string too)
     cpi temp, 0       
     breq endtype     
     pushb [temp]
     rcall emit      ; print the character
     dec counter 
     brne nextchar ; if character left, loop
   endtype:
     ret    

   ; gets max count characters from the user and puts them in the ram buffer
   ; stack (ram-address count - )
   ; this could be expanded to get into rom memory with the spm command 
   geth:
    .db "get n characters into buffer b (B n - )",0
    .dw geth
   getn:
    .dw type        ; backlink
    .db ``get'',3      ; counted name 
   get:
     ; here the logic is
     ;  set up a counter with the max characters
     ;  set Y = X
     ;  start looping:
     ;    key, 
     ;    check if key is $<$enter$>$, if so exit
     ;    store in X; 
     ;  loop
     ;  calculate and store count (max-counter) 
     ;
     ; cant use XH:XL because that is the stack pointer
     popb [counter]      ; maximum characters
     mov param, counter  ; save max chars for count calculation
     popw [YH:YL]
     movw ZH:ZL, YH:YL  ; save pointer for storing count
     adiw YH:YL, 1      ; first byte is count
   nextgetkey:
     rcall key
     popb [temp]
     cpi temp, 13       ; check if $<$enter$>$ pressed
     breq exitget       ; if so, finish
     st Y+, temp 
     dec counter
     brne nextgetkey
   exitget:
     sub param, counter  ; calculate char count
     movw YH:YL, ZH:ZL   ; restore pointer to count byte
     st Y, param 
     ret

   dothexcharh:
    .db "print low byte of t-o-s as unsigned hex (c - )",0     ; help string
    .dw dothexcharh
   dothexcharn:
    .dw get             ; backlink
    .db ``.hexchar'',8,0  ; reverse counted name 
   dothexchar:
     ldi counter, 2
     ; get this from the stack
     popb [param]
   next:
     swap param       ; print high nibble digit first, low 2nd
     mov temp, param 
     andi temp, 0x0F  ; remove high nibble in temp
     cpi temp, 10
     brlo nothex
     subi temp, -7   ; Hex digit so add 8 to get ABCDEF 
   nothex:
     subi temp, -'0' ; add '0' to temp
     pushb [temp]
     rcall emit
     dec counter
     brne next
     ret

   dothexh:
    .db "print top-of-stack as unsigned hex (n - )",0     ; help string
    .dw dothexh
   dothexn:
    .dw dothexchar  ; backlink
    .db ``.hex'',4,0  ; reverse counted name, with zero pad
   dothex:
     rcall dup
     rcall bswap    ; print high byte first
     rcall dothexchar
     rcall dothexchar
     ret

   dotstackh:
    .db "print the stack in hexadecimal ( - )",0     ; help string
    .dw dotstackh
   dotstackn:
    .dw dothexchar  ; previous word in dict
    .db ``.s'',2,0    ; reverse counted name, with padded 0
   dotstack:
     ldi YH, high(stack)  
     ldi YL, low(stack)    
     ; print a stack prefix
     pushc ['s']
     rcall emit
     pushc ['$\}$']
     rcall emit
     pushc [' ']
     rcall emit
     cp YL, XL     ; compare low bytes
     cpc YH, XH    ; compare high bytes (with carry)
     breq stackend ; nothing in stack, so exit
   stacknext:
     ; print a hex prefix
     pushc ['0']
     rcall emit
     pushc ['x']
     rcall emit
     ld templ, Y+
     ld temph, Y+
     pushw [temph:templ]
     rcall dothex
     pushc [' ']
     rcall emit
     cp YL, XL     ; compare low bytes
     cpc YH, XH    ; compare high bytes (with carry)
     brlo stacknext
   stackend:
     rcall newline
     ret

   ; an alias! just does what words does
    .dw 0              ; aliases dont have help
   commandsn:
    .dw dotstack       ; prev word in dict
    .db ``comms '',6,0   ; counted alias name 
   commands:
    .dw words 

   ; the code had a strange bug because I was not doubling the pointer
   ; value correctly (eg add YL, YL; adc YH, YH). When I got into a 
   ; certain memory range the proc went into an infinite loop
   ; this works without doubling the pointer but is unseemly
   ; .db low(typeh$<$$<$1), high(typeh$<$$<$1) 
   ; one tricky thing here is the reverse counts can be upset
   ; by avra padding zeros in uneven numbers of bytes, have to skip
   ; the zero byte
   wordsh:
    .db ``show available commands ( - )'',0     ; help string
    .dw wordsh
   wordsn:
    .dw commands    ; dict back link to alias
    .db ``words'',5   ; counted name 
   words:
     ; pointer to the last proc in dictionary 
     ldi ZH, high(last$<$$<$1) 
     ldi ZL, low(last$<$$<$1)
   nextword:
     ; this is a gotcha, have to double the link, but not for icall
     lpm YL, Z+    ; dereference the pointer in Z reg
     lpm YH, Z
     ; yes! a correct way to double a 16 bit register
     lsl YL 
     rol YH
     ; another way to double the pointer
     ; add YL, YL    
     ; adc YH, YH

     sbiw YH:YL, 0    ; check if pointer is zero (top of dict)
     breq endwords
     sbiw YH:YL, 1    ; point to count byte, or padded zero 
     movw ZH:ZL, YH:YL  
     ; better to use ``counter'' not temp
     lpm temp, Z      ; get the count
     cpi temp, 0
     brne wordscontinue
     sbiw ZH:ZL, 1    ; adjust the pointer over the padded zero
     lpm temp, Z      ; get the count
   wordscontinue:

     ; probably would be better to use a trailing space 
     ; as an alias marker, because we rely on the dict back link
     ; being just infront of the name.
     ; here check if last char of name is space (which signifies an alias)
     ;lpm param, Z      ; get first char
     ;cpi param, ' '    ; check if 1st char is space (alias)
     ;brne wordsnotspace
     ;pushc ['$>$']      ; print an alias marker
     ;rcall emit
   wordsnotspace:

     sub ZL, temp     ; adjust pointer to start of name
     sbc ZH, zero     ; 16bit subtraction

     pushw [ZH:ZL]    ; push address for ``type''
     rcall dup        ; save the pointer
     pushb [temp]     ; count on stack
     pushc [0]        ; rom flag (not sram) for type
     rcall type       ; print the proc name
     pushc [' ']
     rcall emit
     popw [ZH:ZL]     ; restore pointer
     sbiw ZH:ZL, 2    ; point to back-link
     rjmp nextword
   endwords:
     rcall newline
     ret    

   newlineh:
    .db ``print a newline'',0 
    .dw newlineh
   ; or just '0' for no help
   newlinen:
    .dw words
    .db ``newline'',7 
   newline:
     pushc [13]      ; \textbackslash n char
     rcall emit
     pushc [10]      ; \textbackslash r char
     rcall emit
     ret

   ; change this to check for a zero backlink, which indicates
   ; absence of help string. Help string will be zero terminated
   ; Help header will go before name header
   ; and will have struct
   ;   commandh:
   ;     .db ``help string for command'', 0
   ;     .dw commandh   ; link to help header, this can be zero
   helph:
    .db ``show help for commands ( - )'',0
    .dw helph
   helpn:
    .dw newline
    .db ``help'',4,0   ; proc name with rev count 
   help:
     ; pointer to the last proc in dictionary 
     ldi ZH, high(last$<$$<$1) 
     ldi ZL, low(last$<$$<$1)
   nexthelp:
     lpm YL, Z+    ; dereference the pointer in Z reg
     lpm YH, Z
     ; must double pointer
     add YL, YL    
     adc YH, YH
     sbiw YH:YL, 0    ; check if pointer is zero (top of dict)
     breq endhelp

     sbiw YH:YL, 1    ; point to count byte, or padded zero 
     movw ZH:ZL, YH:YL  
     lpm counter, Z      ; get the count
     cpi counter, 0
     brne helpcontinue
     sbiw ZH:ZL, 1    ; adjust the pointer over the padded zero
     lpm counter, Z      ; get the count
   helpcontinue:
     sub ZL, counter  ; adjust pointer to start of name
     sbc ZH, zero     ; 16bit subtraction
     pushw [ZH:ZL]    ; push address for ``type'' to use
     rcall dup        ; save the pointer
     pushb [counter]  ; count on stack
     pushc [0]        ; rom flag (not sram) for type
     rcall type       ; print the proc name
     rcall newline
     popw [ZH:ZL]     ; restore pointer
     sbiw ZH:ZL, 2    ; point to back-link
     pushw [ZH:ZL]    ; save pointer again 
     sbiw ZH:ZL, 2    ; point to help link 

     lpm YL, Z+     ; dereference the pointer in Z reg
     lpm YH, Z      ;  
     ; must double pointer
     add YL, YL    
     adc YH, YH
     sbiw YH:YL, 0    ; check if pointer is zero (no help header)
     breq nohelpheader 
     pushw [YH:YL]    ; push help header point for ``type'' to use
     pushc [200]      ; help string is zero terminated
     pushc [0]        ; type rom not sram flag
     pushc [' ']      ; print 2 spaces before the help
     rcall emit
     pushc [' ']
     rcall emit
     rcall type
   nohelpheader:
     rcall newline
     popw [ZH:ZL]     ; restore pointer to next command in dict
     rjmp nexthelp
   endhelp:
     ret    
   
   ; this may need 2 more params on the stack ram/rom flags ?
   ; stack: ( A B flag flag )

   ; compares a counted string is program memory with one in sram
   ; this will be used by find, pointers to strings are on the stack
   ; rom string on top of stack, ram string pointer underneath
   ; working.
   compareh:
    .db "compares n chars of 2 strings in rom and ram (A.sram n A.rom - flag)",0
    .dw compareh
   comparen:
    .dw help 
    .db ``compare'',7
   compare:
     popw [ZH:ZL]    ; pointer to counted string in rom 
     popb [counter]  ; how many chars to compare
     popw [YH:YL]    ; pointer to string in sram
     ;dont compare count !
   nextcompare:     ; use string count to count the loop
     lpm temp, Z+
     ld param, Y+
     cp temp, param
     brne notequal
     dec counter
     ; loop until no more chars
     brne nextcompare
   equal:
     pushc [1]   ; success flag on stack
     ret
   notequal:
     pushc [0]   ; failure flag 
     ret
     
   ; this word allows us to search names and the help strings to find
   ; a word/command. Or return the location and length or 0,0
   containsh:
    .db "check if buffer A.prog contain string A.data (A.data n A.prog m - flag)",0
    .dw containsh
   containsn:
    .dw compare
    .db ``contains'',8,0  ; reverse count with zero pad
   contains:
     ret
     
   ; finds a command and executes it
   ; this uses a similar process to ``help'' and words, looping
   ; through the dictionary.
   ; copy ``words'' code
   ; should take address and count as parameters
   findh:
    .db "find a command and execute it (A n - xt|0) ",13,10
    .db "returns 0 if name not found, else exec address",0
    .dw findh
   findn:
    .dw contains 
    .db ``find'',4,0   ; procedure name with count
   find:
     ; pointer to the last proc in dictionary 
     ldi ZH, high(last$<$$<$1) 
     ldi ZL, low(last$<$$<$1)
     popb [param]         ; get the name count
     popw [temph:templ]   ; pointer to name buffer 
   nextfind:
     lpm YL, Z+    ; dereference the pointer in Z reg
     lpm YH, Z
     ; must double pointer
     add YL, YL    
     adc YH, YH

     sbiw YH:YL, 0    ; check if pointer is zero (top of dict)
     breq endfind
     pushw [YH:YL]    ; save pointer to exec address in case 

     sbiw YH:YL, 1    ; point to count byte, or padded zero 
     movw ZH:ZL, YH:YL  
     ; better to use ``counter'' not temp
     lpm temp, Z      ; get the count
     cpi temp, 0
     brne findcontinue
     sbiw ZH:ZL, 1    ; adjust the pointer over the padded zero
     lpm temp, Z      ; get the count
   findcontinue:
     sub ZL, temp     ; adjust pointer to start of name
     sbc ZH, zero     ; 16bit subtraction


     cp temp, param   ; compare 2 counts
     brne findagain   ; if counts not equal, try next word in dict

     ; check for alias here
   findnotspace:

     pushw [ZH:ZL]    ; save Z before compare, because it mods it 
     pushb [param]    ; save param too
     ; set up stack for ``compare'' (P.sram n P.rom - 0/1)
     pushw [temph:templ]
     pushb [temp]     ; push the count
     pushw [ZH:ZL]    ; pointer to name in rom

     ;pushw [temph:templ]
     ;rcall dotstack
     ;popw [temph:templ]

     rcall compare
     popb [temp]      ; get result of compare  
     popb [param]
     popw [ZH:ZL]
     cpi temp, 0
     breq findagain   ; if not same, try next word
     ; success! exec address already on stack
     ; pushc [1]
     ret

   findagain:

     rcall drop       ; get rid of pointer to exec address
     sbiw ZH:ZL, 2    ; point to back-link
     rjmp nextfind
   endfind:
     pushc [0]   ; word not found flag
     ret    

   starh:
    .db ``print a star''",0 
    .dw starh
   starn:
    .dw find
    .db ``star'',4,0
   star:
    pushc ['*']
    rcall emit
    ret

   ; this is forth ``execute'' or ``perform''
   ; working! after division by 2!
   doh:
    .db "execute address on stack (xp - )",0 
    .dw doh
   don:
    .dw star 
    .db ``do'',2,0
   do:
    popw [ZH:ZL]
    ; divide address by 2 for icall
    lsr ZH
    ror ZL
    icall
    ret

   interpreth:
    .db "accept 1 command and execute it ( - )",0 
    .dw interpreth
   interpretn:
    .dw do 
    .db ``interpret'',9
   interpret:
   interpagain: 
     ; this is the skeleton code for ``interpret'' which
     ; just interprets 1 word. 
     pushc ['$>$']   ; print a prompt
     rcall emit
     ldi ZH, high(input)
     ldi ZL, low(input)
     pushw [ZH:ZL]  ; save for find 
     pushw [ZH:ZL]  ; where to put in sram
     pushc [32]     ; maximum number of chars
     rcall get
     pushc [1]    ; type sram not rom
     rcall count
     call drop
     ;rcall dotstack
     rcall find 
     ;rcall dotstack
     rcall do
     rjmp interpagain
     ; never exits
     ret

   ; a pointer to the last word in the dictionary
   last:
     .dw do
     
  ,,,

\emph{ An 8 bit implementation  }
  --------
   .ifdef 0
      uses an 8 bit stack with a procedure header with name and
      help string. will try to search for a procedure name and 
      execute, can print command names and help 

      Modify to use a software datastack, using X reg as the 
      top of stack pointer. This should make parameter passing easier
      (no juggling) and also allows proceedures to be used as opcodes
      in a bytecode system. Also, change the help header struct
      as above. 

   .endif

   .nolist
   .include ``m328Pdef.inc''    ; the atmega328p, the usual arduino uC
   .list

   .def temp = r20       ; short term calculations 
   .def counter = r16    ; counter loops etc
   .def param = r24      ; used for local parameters
   .def zero = r0        ; just contains zero 

   .dseg       
     ; a 20 byte buffer for typed commands
     input:
      .byte 30
     stack:
      .byte 128
   .cseg        ; rom program memory (flash)
   .org 0
   jmp start
   start:
     ; assume auto initialisation of stack
     ; test dup key and emit

     ; set up X as a software data stack pointer 
     ldi xh, high(stack)  
     ldi xl, low(stack)    
     rcall serial

   here: 
     clr zero       ; keep zero register=0
     ldi temp, '['  ; print a prompt
     push temp 
     rcall emit
  
     rcall get 
     rcall newline
     ; rjmp nope
     ; test compare
     ldi ZH, high(data$<$$<$1)
     ldi ZL, low(data$<$$<$1)
     ldi XH, high(input)
     ldi XL, low(input)
     push XL
     push XH
     push ZL
     push ZH
     rcall compare
     ; check the result
     pop temp
     cpi temp, 1
     ; if not the same then skip
     brne nope
     ldi temp, 'Y'
     push temp
     rcall emit
   nope:

     rcall words 
     rcall newline
     rcall help

     ldi temp, '.'
     push temp 
     rcall emit
     rcall newline

     rjmp here 

   data: 
     .db 4, ``what''

   ; initialize an rs232 serial connection using onboard usart
   ; no header because it cant be used interactively.
   serial:
     ldi r16, 1$<$$<$TXEN0 | 1$<$$<$RXEN0     ; enable transmit receive 
     sts UCSR0B, r16       
     ldi r16, 1$<$$<$UCSZ01 | 1$<$$<$UCSZ00
     sts UCSR0C, r16      
     ldi r16, 0x66    ; the baud rate, 9600 on 16 megaherz chip
     sts UBRR0L, r16
     ldi r16, 0x00    ; the baud rate, 9600
     sts UBRR0H, r16
     ret

   ; duplicate the top (8bit) stack item
   duph:
    .dw 0         ; 1st procedure, so no backlink
    .db 3, ``dup''  ; command name 
   dups:
    .db (dup-dups-1)*2
    .db ``duplicate top item of stack''    ; help string
   dup:
     pop ZH     ; return address into Z reg
     pop ZL
     pop temp   ; top-of-stack 
     push temp  ; push t-o-s twice to duplicate
     push temp
     ijmp       ; a trick! because ret address is in Z reg 

   keyh:
    .dw duph      ; a back-link in the linked-list dict
    .db 3, ``key''  ; 
   keys:
    .db (key-keys-1)*2
    .db "receive one character from keyboard"    ; help string
   key:
   wait:
     lds temp, UCSR0A   ; get usart status info
     sbrs temp, RXC0    ; has a byte been received?
     rjmp wait          ; if not just wait for one.
     lds temp, udr0     ; get received byte
     pop ZH
     pop ZL
     ; push the char onto the stack
     push temp
     ijmp       ; equivalent to ``push zl;push zh; ret''

   ; using the stack to pass parameters is like a protocol
   ; transmit 1 character in r17 over serial connection
   ; here is the header for the procedure
   emith:
    .dw keyh         ; a link to previous word
    .db 4, ``emit''    ; procedure name with count
   emits:
    ; !careful, the compiler pads extra zero in uneven addresses
    ; so this count arithmetic may not work.
    .db (emit-emits-1)*2 
    .db "print character on top of stack"    ; help string
   emit:
   transmit:
     lds temp, UCSR0A ; usart control, status register
     sbrs temp, UDRE0 ; is UDR empty?
     rjmp transmit    ; if not, then just wait (block)
     ; maybe better not to use Z reg, because lpm and spm 
     ; can only use Z and Z+
     pop ZH    ; high byte of ret address into r31
     pop ZL    ; low byte of ret address in r30 
     pop temp  ; get character to transmit 
     sts UDR0, temp  ; if empty tx character
     ijmp             ; return to caller (return address already in Z reg)

   counth:
    .dw emith        ; backlink
    .db 5, ``count''   ; counted name 
   counts:
    .db (count-counts-1)*2
    .db "puts count on stack and increments pointer"  
   count:
     pop YH    ; return address of proc
     pop YL    ; low byte
     pop ZH    ; high byte of pointer to counted string
     pop ZL    ; low byte
     lpm temp, Z+  ; get count
     push ZL
     push ZH
     push temp
     push YL   ; restore return address 
     push YH   ; 
     ret    

   ; actually type doesnt work like this. It should have a count and a 
   ; pointer on the stack. Then it prints 
   ; Also, this type needs to also work for eeprom and sram. So it 
   ; needs to check what memory it is dealing with. In sram it uses
   ; ``ld'' instruction but in rom it uses ``lpm'' etc.

   ; this also needs to terminate printing if a zero byte is found.
   typeh:
    .dw counth       ; backlink
    .db 4, ``type''    ; counted name 
   types:
    .db (type-types-1)*2
    .db ``print a counted string''    ; help string
   type:
     pop YH    ; return address of proc
     pop YL    ; low byte
     pop ZH    ; high byte of pointer to string
     pop ZL    ; low byte
     push YL   ; restore return address 
     push YH   ; 

     lpm counter, Z+  ; get count
     cpi counter, 0   ; if count is zero, exit
     breq endtype
   nextchar:
     lpm temp, Z+   ; get next character
     ; here check for zero and terminate (so prints "c" style string too)
     cpi temp, 0
     breq endtype

     push ZL        ; emit uses Z reg so must be saved (or change emit)
     push ZH
     push temp
     rcall emit    ; print the character
     pop ZH
     pop ZL
     dec counter 
     brne nextchar ; if character left, loop
   endtype:
     ret    

   ; gets max 10 characters from the user and puts them in the buffer
   geth:
    .dw typeh         ; backlink
    .db 3, ``get''      ; counted name 
   gets:
    .db (get-gets-1)*2
    .db "get some characters into buffer"  
   get:
     ; here the logic is
     ;  set up a counter with the max characters
     ;  set Y = X
     ;  start looping:
     ;    key, 
     ;    check if key is $<$enter$>$, if so exit
     ;    store in X; 
     ;  loop
     ;  calculate and store count (max-counter) 
     ;
     ldi XL, low(input)
     ldi XH, high(input)
     movw YH:YL, XH:XL  ; save pointer for storing count
     adiw XH:XL, 1      ; first byte is count
     ldi counter, 10    ; maximum characters
   nextgetkey:
     rcall key
     pop temp
     cpi temp, 13       ; check if $<$enter$>$ pressed
     breq exitget       ; if so, finish
     st X+, temp 
     dec counter
     brne nextgetkey
   exitget:
     ldi temp, 10      ; calculate and store the char count
     sub temp, counter
     st Y, temp
     ret

   ; the code had a strange bug because I was not doubling the pointer
   ; value correctly (eg add YL, YL; adc YH, YH). When I got into a 
   ; certain memory range the proc went into an infinite loop

   ; this works without doubling the pointer but is unseemly
   ; .db low(typeh$<$$<$1), high(typeh$<$$<$1) 
   wordsh:
    .dw geth        ; back link 
    .db 5,``words''   ; counted name 
   wordss:
    .db (words-wordss-1)*2            ; calculated count of help string
    .db ``show available commands''     ; help string
   words:
     ; pointer to the last proc in dictionary 
     ldi ZH, high(last$<$$<$1) 
     ldi ZL, low(last$<$$<$1)

   nextword:
     ; this is a gotcha, have to double the link, but not for icall
     lpm YL, Z+    ; dereference the pointer in Z reg
     lpm YH, Z
     ; yes! a correct way to double a 16 bit register
     lsl YL 
     rol YH
     ; another way to double the pointer
     ; add YL, YL    
     ; adc YH, YH

     sbiw YH:YL, 0    ; check if pointer is zero (top of dict)
     breq endwords

     push YL          ; save a copy of the pointer
     push YH
     adiw YH:YL, 2    ; point to counted name
     push YL          ; put the pointer on the stack
     push YH
     rcall type       ; print the proc name

     ldi temp, ' '
     push temp
     rcall emit
     pop ZH        ; restore pointer to next word in dict
     pop ZL
     rjmp nextword
   endwords:
     ret    

   newlineh:
    .dw wordsh       
    .db 7, ``newline'' 
   newlines:
    .db (newline-newlines-1)*2  ; calculated count
    .db ``print a newline''       ; help string
   newline:
     ldi temp, 13
     push temp
     rcall emit
     ldi temp, 10
     push temp
     rcall emit
     ret

   ; change this to check for a zero backlink, which indicates
   ; absence of help string. Help string will be zero terminated
   ; Help header will go before name header
   ; and will have struct
   ;   commands:
   ;     .db ``help string for command'', 0
   ;     .dw commands   ; link to help header, this can be zero
   helph:
    .dw newlineh 
    .db 4, ``help''   ; procedure name with count
   helps:
    .db (help-helps-1)*2
    .db ``show help for commands''
   help:
     ; ``last'' is pointer to the last command in dictionary 
     ldi ZH, high(last$<$$<$1) 
     ldi ZL, low(last$<$$<$1)
   nexthelp:
     lpm YL, Z+    ; dereference the pointer in Z reg
     lpm YH, Z
     ; one way to double a 16 bit register. This has to be doubled
     ; because rom is word (16bit) addressed
     add YL, YL    
     adc YH, YH
     sbiw YH:YL, 0    ; check if pointer is zero (top of dict)
     breq endhelp
     push YL          ; save a copy of the pointer
     push YH
     adiw YH:YL, 2    ; point to counted name
     push YL          ; put the pointer on the stack
     push YH
     push YL          ; save another copy
     push YH
     rcall type       ; print the proc name
     ldi temp, ':'    ; print a :
     push temp
     rcall emit
     rcall newline
     ldi temp, ' '    ; print a space
     push temp
     rcall emit
     pop ZH           ; get pointer to name count byte
     pop ZL
     lpm temp, Z      ; get count
     inc temp         ; +1 
     ; but here we need logic to see if we are at an odd
     ; numbered address, and if so, increment. Or we could check for zero.
     add ZL, temp     ; add count to Z
     adc ZH, zero

     ; the method below is not really correct, should use an odd/even test
     ; check if zero byte (extra padded)
     lpm temp, Z      ; if this is a zero byte, we assume its been padded 
     cpi temp, 0      ; by the compiler
     brne notzero
     adiw ZH:ZL, 1    ; skip over the zero byte
   notzero:
    ; maybe another way, not working
    ; sbrc temp,0    ; if lsb is 0 skip next increment instruction
    ; adiw ZH:ZL, 1  ; skip over the padded zero byte

     push ZL
     push ZH       ; push the pointer for ``type'' to use
     rcall type    ; print the command help
     ldi temp, '.' 
     push temp
     rcall emit
     rcall newline

     pop ZH        ; restore back pointer to next word in dict
     pop ZL
     rjmp nexthelp
   endhelp:
     ;ldi temp, '\#'
     ;push temp
     ;rcall emit
     ret    
   
   ; compares a counted string is program memory with one in sram
   ; this will be used by find, pointers to strings are on the stack
   ; rom string on top of stack, ram string pointer underneath
   ; working.
   compareh:
    .dw helph 
    .db 7, ``compare''  
   compares:
    .db (compare-compares-1)*2
    .db "compares 2 counted strings in rom and ram"
   compare:
     pop YH    ; save ret address
     pop YL
     pop ZH    ; pointer to counted string in rom 
     pop ZL
     pop XH    ; pointer to counted string in ram
     pop XL
     lpm temp, Z+    ; load string counts and compare
     ld counter, X+  ; use the string count to count the loop
     cp temp, counter 
     brne notequal
   nextcompare:
     lpm temp, Z+
     ld param, X+
     cp temp, param
     brne notequal
     dec counter
     ; loop until no more chars
     brne nextcompare
   equal:
     ldi temp, 1   ; success flag on stack
     push temp
     push YL   ; restore address
     push YH
     ret
   notequal:
     ldi temp, 0   ; failure flag
     push temp
     push YL   ; restore address
     push YH
     ret
     
   ; finds a command an executes it
   ; this uses a similar process to ``help'' and words, looping
   ; through the dictionary.
   findh:
    .dw compareh 
    .db 4, ``find''   ; procedure name with count
   finds:
    .db (find-finds-1)*2
    .db ``find a comm and execute it''
   find:
     ; ``last'' is pointer to the last command in dictionary 
     ldi ZH, high(last$<$$<$1) 
     ldi ZL, low(last$<$$<$1)
   nextfind:
     lpm YL, Z+    ; dereference the pointer in Z reg
     lpm YH, Z
     ; one way to double a 16 bit register. This has to be double 
     ; because rom is word (16bit) addressed
     add YL, YL    
     adc YH, YH
     sbiw YH:YL, 0    ; check if pointer is zero (top of dict)
     breq endfind
     push YL          ; save a copy of the pointer
     push YH
     adiw YH:YL, 2    ; point to counted name
     push YL          ; put the pointer on the stack
     push YH
     push YL          ; save another copy
     push YH

     ; check here if name is the same as the buffer
     rcall type       ; print the proc name
     pop ZH           ; get pointer to name count byte
     pop ZL
     lpm temp, Z      ; get count
     inc temp         ; +1 
     add ZL, temp     ; add count to Z
     adc ZH, zero
     ; but here we need logic to see if we are at an odd
     ; numbered address, and if so, increment. Or we could check for zero.

     ; the method below is not really correct, should use an odd/even test
     ; check if zero byte (extra padded)
     lpm temp, Z      ; if this is a zero byte, we assume its been padded 
     cpi temp, 0      ; by the compiler
     brne notazero
     adiw ZH:ZL, 1    ; skip over the zero byte
   notazero:
    ; maybe another way, not working
    ; sbrc temp,0    ; if lsb is 0 skip next increment instruction
    ; adiw ZH:ZL, 1  ; skip over the padded zero byte

     push ZL
     push ZH       ; push the pointer for ``type'' to use
     rcall type    ; print the command help
     ldi temp, '.' 
     push temp
     rcall emit
     rcall newline
     pop ZH        ; restore back pointer to next word in dict
     pop ZL
     rjmp nextfind
   endfind:
     ret    

   ; a pointer to the last word in the dictionary
   last:
     .dw findh
     
  ,,,

\section{Byte Code And Virtual Machines}

  An important idea!:
    use the atmega ``hardware'' stack for a ``return'' stack (in forth terminology)
    Then create a new, software stack (16bit) for the data stack.
    This has lots of advantages; we dont need to juggle data on the hardware
    stack, we can right commands/words as normal call/ret proceedures, and
    test them like normal procs. I can then convert that to a bytecode system.

  One step on the path to implementing a portable forth system, may
  be to develop a ``byte-code'' system. This means that opcodes (0-255)
  execute specific functions which create a virtual machine.
  We can use the avr instruction 'ijmp' or 'icall' to implement this 
  byte code system.

  The icalls are working, now we need load the correct optable offset
  and then load correct jump address into Z register.

  A byte code forth-like virtual machine needs the following instructions
    - 2 stacks: a general data stack and a return stack, where procedure
      addresses are stored
    - stack manipulation eg + dup drop etc
    - ``exec'' or ``call'' to call a virtual (byte code) procedure
      equivalent to ``call'' or ``icall'' on the atmega328
    - ``return'' or ``exit'' to exit from the virtual proceedure
      equivalent to ``ret'' on a real uC
    - unconditional jumps
    - conditional jumps eg ``jumpz'' , jump if the top stack item is zero
      equivalent to ``breq'' or ``brne'' on the 328P

  The basic procedure for bytecode execution is...
    ( the opcode execution loop. )
    ;  set PC pointer=Z register (saved in r23:r22) 
    ;  load next opcode into reg and increment ip
    ;  compare to zero? and halt?
    ;  double the opcode (word pointer)
    ;  add offset to optable. 
    ;  do ijmp/icall to address

  The example with a 'jump' instruction is more complete.

  The code below uses lots of ideas from the FORTH language, eg a linked-list 
  ``dictionary'' of procedures where each item in the dictionary contains
  the procedure name and a link back to the previous procedure (or 0 if it
  is the 1st procedure). This is really useful because it allows procedures 
  to be used interactively. 
  
  But to make the system better, we need a procedure that looks up a name and
  executes it. Also, it would be nice to have a way to get numbers onto the
  stack, this means that we can run procedures with parameters. Also, it would
  be good to have a ``help'' function which displays a list of procedures and
  what they do. This would provide a minimal interactive read-only forth-like
  system and would be very handy for communicating with a microcontroller 
  over a serial connection.

\emph{ A basic byte code system in avr assembly }
  ------
  .nolist
  .include ``m328Pdef.inc''
  .list

    .def pch = r23 
    .def pcl = r22
    .def temp = r16
    .def zero = r1

    .equ DUP = 1 
    .equ EMIT = DUP+1 
    .equ KEY = EMIT+1 
    .equ STAR = KEY+1 

   .dseg
   ; ram data segment 
   .cseg
   ; start of flash ``rom'' code segment

   .org 0
   jmp start 
   ; ISR vectors here

   start:
    ; assume stack auto initialised 
    rcall serialx    ; set up serial interface
    clr zero

    ; again: ldi zh, high(emitx) ldi zl, low(emitx) icall jmp again
    ; again: call keyx call emitx jmp again

    ; r23:r22 PC program counter

    ; put all this in an exec function.
    ; lpm=load program memory, must use Z register
    ldi r23, high(code$<$$<$1) 
    ldi r22, low(code$<$$<$1)

   nextopcode:
    ; retrieve and save PC program counter to r23:r22
    movw ZH:ZL, r23:r22     ; get ip 
    lpm r20, Z+
    movw r23:r22, ZH:ZL     ; save ip 
    rjmp checkzero

   ; just for debugging opcode retrieval
   digit:
     lds r16, UCSR0A    ; usart control, status register
     sbrs r16, UDRE0    ; is UDR empty?
     rjmp digit         ; if not, then just wait 
     ldi r17, '0'       ; convert opcode to asci digit
     mov r16, r20       ; assumes 0 $<$ opcode $<$ 10
     add r16, r17
     sts UDR0, r16      ; if empty tx next character
     
   checkzero:
    ; halt if opcode is zero
    cpi r20, 0 
    breq goodbye 

    ldi ZH, high(optable$<$$<$1) 
    ldi ZL, low(optable$<$$<$1)
    add ZL, r20    ; opcode number (need to double)
    adc ZH, zero
    add ZL, r20    ; 
    adc ZH, zero
    lpm r16, Z+
    lpm r17, Z+
    movw ZH:ZL, r17:r16     ;  
    ;ldi ZH, high(starx$<$$<$1) 
    ;ldi ZL, low(starx$<$$<$1)
    icall

    rjmp nextopcode

   goodbye:

    lds temp, UCSR0A     ; usart control, status register
    sbrs temp, UDRE0     ; is UDR empty?
    rjmp goodbye         ; if not, then just wait 
    ldi temp, '!'
    sts UDR0, temp       ; if empty tx next character

   here: 
    rjmp here

   code:
     ; some bytecode to test the system
     .db STAR, KEY, EMIT, KEY, EMIT, KEY, EMIT, 0
   ; pointers to opcode functions. 
   optable:
     .dw 0, dupx, emitx, keyx, starx
   
   ; duplicates the top stack item
   duph:
    .dw 0          ; this is 1st proc, so backlink=0
    .db 3, ``dup''   ; the proc name + count
   dupx:
     ; here need to juggle the stack because the top 2 items
     ; are the return address from the function
     pop ZH     ; return address into Z reg
     pop ZL
     pop r16    ; low byte of top of stack
     pop r17    ; high byte, but reversed??
     push r17
     push r16
     push r17
     push r16
     ijmp       ; a trick! because ret address is in Z reg 

   emith:
    .dw dupx       ; a link back to previous word 
    .db 4, ``emit''  ; the proc name + count
   emitx:
    transmit:
     ; sbis doesnt work because ucsr0a is not in standard
     ; i/o space so it cant be used with sbis (skip if bit in i/o is set)
     lds r16, UCSR0A       ; usart control, status register
     sbrs r16, UDRE0       ; is UDR empty?
     rjmp transmit         ; if not, then just wait 
     ; this should be got from the stack
     ldi r17, '\#'    
     sts UDR0, r17          ; if empty tx next character
     ret
     
   keyh:
    .dw emitx 
    .db ``key'', 3
   keyx:
   wait:
     lds r16, UCSR0A    ; get usart status info
     sbrs r16, RXC0     ; has a byte been received?
     rjmp wait          ; if not just wait for one.
     lds r17, udr0      ; get received byte
     ; now push the char onto the stack
     ret

   starh:
    .dw 0 
    .db 4, ``star''
   starx:
    waithere:
     lds r16, UCSR0A       ; usart control, status register
     sbrs r16, UDRE0       ; is UDR empty?
     rjmp waithere         ; if not, then just wait 
     ldi r17, '*'    
     sts UDR0, r17         ; if empty tx next character
     ret
     
   ; set up the usart serial interface for the atmega328
   serialx:
     ldi r16, 1$<$$<$TXEN0 | 1$<$$<$RXEN0     ; enable transmit receive 
     sts UCSR0B, r16       
     ldi r16, 1$<$$<$UCSZ01 | 1$<$$<$UCSZ00
     sts UCSR0C, r16      
     ldi r16,0x66    ; the baud rate, 9600 on 16 megaherz chip
     sts UBRR0L,r16
     ldi r16,0x00    ; the baud rate, 9600
     sts UBRR0H,r16
     ret

  ,,,


  The purpose of using the JMP or IJMP instruction to run procedures is
  to free up the (8 bit) avr data stack for passing parameters to
  and from procedures. If we use CALL or ICALL, then we need to 'juggle'
  the procedure return address. Another improvement is to 'cache' the 
  top (16 bit) element of the stack in a register pair. Eg the register
  pair just below the X register

  The code below really needs an ``fcall'' or ``exec'' function which can
  execute a series of byte codes. Also needs an ``exit/return'' to exit from 
  a virtual proc. 

  Still need ``call'', ``return''

\emph{ A bytecode system using jmp not call  }
  ------
  .nolist
  .include ``m328Pdef.inc''
  .list

    .equ DUP = 1 
    .equ EMIT = DUP+1 
    .equ KEY = EMIT+1 
    .equ STAR = KEY+1 

   .dseg
   ; ram data segment 
   .cseg
   ; start of flash ``rom'' code segment

   .org 0x0000

   jmp wakeup

   ; pointers to opcode functions. 
   optable:
     .dw 0, dupx, emitx, keyx, starx
   
   ; 
   execx:
     jmp nextopcode 

   ; duplicates the top stack item
   duph:
   dupx:
     pop r16       ; low byte of top of stack (reversed??)
     pop r17       ; high byte of top-of-stack
     push r17
     push r16
     push r17
     push r16
     jmp nextopcode 

   emith:
    .dw dupx       ; the classic dictionary backlink
    .db ``emit'', 4
   emitx:
     waitagain:
     lds r16, UCSR0A       ; usart control, status register
     sbrs r16, UDRE0       ; is UDR empty?
     rjmp waitagain        ; if not, then just wait 
     pop r17               ; low byte  (character)
     pop r18               ; high byte (should be zero)
     sts UDR0, r17         ; if empty tx character
     jmp nextopcode 
     
   keyh:
    .dw emitx 
    .db ``key'', 3
   keyx:

   wait:
     lds r16, UCSR0A    ; get usart status info
     sbrs r16, RXC0     ; has a byte been received?
     rjmp wait          ; if not just wait for one.
     lds r17, udr0      ; get received byte
     ; now push the char onto the stack
     ldi r16, 0
     push r16       ; high byte
     push r17       ; low byte (character)
     jmp nextopcode 

   starh:
    .dw 0 
    .db ``star'', 4
   starx:
    waithere:
     lds r16, UCSR0A       ; usart control, status register
     sbrs r16, UDRE0       ; is UDR empty?
     rjmp waithere         ; if not, then just wait 
     ldi r17, '*'    
     sts UDR0, r17         ; if empty tx next character
     jmp nextopcode 
     
   ; initialize an rs232 serial connection using onboard usart
   ; this cant really be used interactively so is not a forth-style command
   ; with header etc
   serialx:
     ldi r16, 1$<$$<$TXEN0 | 1$<$$<$RXEN0     ; enable transmit receive 
     sts UCSR0B, r16       
     ldi r16, 1$<$$<$UCSZ01 | 1$<$$<$UCSZ00
     sts UCSR0C, r16      
     ldi r16, 0x66    ; the baud rate, 9600 on 16 megaherz chip
     sts UBRR0L, r16
     ldi r16, 0x00    ; the baud rate, 9600
     sts UBRR0H, r16
     ret

   code:
     ; some bytecode to test the system
     .db STAR, STAR, KEY, DUP, EMIT, EMIT
     .db KEY, DUP, EMIT, EMIT, 0

   wakeup:
    ; initialise the stack at the top of ram
    ldi r21, high(ramend)  
    out sph, r21        
    ldi r21, low(ramend)    
    out spl, r21        
   
    call serialx    ; set up serial interface

    ; r25:r24 could hold top of stack
    ; r23:r22 PC program counter
    ; put all this in an exec function.
    ; lpm=load program memory, must use Z register
    ldi r23, high(code$<$$<$1) 
    ldi r22, low(code$<$$<$1)

   nextopcode:
    ; retrieve and save PC program counter to r23:r22
    movw ZH:ZL, r23:r22     ; get ip 
    lpm r20, Z+
    movw r23:r22, ZH:ZL     ; save ip 

    ; rcall digit ; 

   checkzero:
    ; halt if opcode is zero
    cpi r20, 0 
    breq goodbye 

    ; this looks wrong: check! need to do ``add'' then ``adc'' on ZH:ZL
    ldi ZH, high(optable$<$$<$1) 
    ldi ZL, low(optable$<$$<$1)
    add ZL, r20    ; opcode number (need to double?)
    add ZL, r20    ; 
    ; try the following to double opcode
    ; add ZL, r20
    ; adc ZH, 0
    ; add ZL, r20
    ; adc ZH, 0

    ; load the function address into Z via r17:r16
    lpm r16, Z+
    lpm r17, Z+
    movw ZH:ZL, r17:r16     ;  
    ijmp

    ; never executed I think
    ; jmp nextopcode

   goodbye:
    lds r16, UCSR0A     ; usart control, status register
    sbrs r16, UDRE0     ; is UDR empty?
    rjmp goodbye        ; if not, then just wait 
    ldi r20, '.'
    sts UDR0, r20       ; if empty tx character
   here: rjmp here

   ; just for debugging opcode retrieval
   digit:
     lds r16, UCSR0A    ; usart control, status register
     sbrs r16, UDRE0    ; is UDR empty?
     rjmp digit         ; if not, then just wait 
     ldi r17, '0'       ; convert opcode to asci digit
     mov r16, r20       ; assumes 0 $<$ opcode $<$ 10
     add r16, r17
     sts UDR0, r16      ; if empty tx next character
     ret

  ,,,


  We can use DEFs to make this more readable.
   eg:
    .def pch = r23  ; (program counter high byte)
    .def pcl = r22
    .def tosh = r25 ; (top-of-stack high byte)
    .def tosl = r24 


  The system below, if it starts to work, edges towards being a useful
  ``repl'' system, where the user can enter commands over the serial connection.
  But we really need an ``fcall'' opcode so that we can call proceedures.

  Added jumpnz jump if non zero

\emph{ A bytecode system with ijmp and top-of-stack in r25:r24 }
  ------

  .nolist
  .include ``m328Pdef.inc''
  .list

   .ifdef 0
      1 april 2020, tested and working on ``duemilanove''
      I changed the code for calculating the program counter offset with
      'jump' instructions.

      The code is structured as a linked list dictionary, which is the system
      used in all forth systems, but here the dictionary is not used because
      there is no ``lookup'' of words (just execution of 'opcodes').
       
      This is the most complete bytecode example, but to be useful as 
      a virtual machine, it needs opcodes ``call'', ``return'', ``jumpz''

      5 may 2020:
        about 450 bytes in size, with no headers or help strings. also, 
        no ``lit'' and litw for pushing literal values on the stack

   .endif

    ; pch:pcl is the "Y" register which allows using sbiw and adiw instructions
    .def pch = r29  ; (program counter high byte)
    .def pcl = r28
    .def tosh = r25 ; (top-of-stack high byte)
    .def tosl = r24 ; the data stack is the atmega stack

    ; the return stack is used by ``call/fcall/exec'' and ``return/exit''
    ; the word ``call'' is a reserved word in many assemblers, hence ``fcall''

    .def rsh = r23  ; return stack pointer, high byte
    .def rsl = r22  ; return stack pointer, low byte
    .def zero = r2 
    .def temp = r16
    .def opcode = r20

    .equ DUP = 1 
    .equ DROP = DUP+1 
    .equ NOT = DROP+1   
    .equ INCR = NOT+1 
    .equ DECR = INCR+1 
    .equ EMIT = DECR+1 
    .equ KEY = EMIT+1 
    .equ JUMP = KEY+1 
    .equ JUMPNZ = JUMP+1 
    .equ FCALL = JUMPNZ+1 
    .equ RETURN = FCALL+1 
    .equ STAR = RETURN+1 

   .dseg
   ; ram data segment 
   .cseg
   ; start of flash ``rom'' code segment

   .org 0x0000

   jmp start
   ; ISR jump vectors go here.

   start:

    ; initialise the data stack at the top of ram
    ; this is not really required
    ldi temp, high(RAMEND)  
    out SPH, temp 
    ldi temp, low(RAMEND)    
    out SPL, temp 

    ; set up the forth-like return stack, like data stack, it grows up towards
    ; the data stack. This leaves about 750 bytes of data memory
    ldi RSH, high(RAMEND-256)
    ldi RSL, low(RAMEND-256)    

    clr zero        ; set r2 = 0 
    call serialx    ; set up serial interface

    ; lpm=load program memory, must use Z register
    ldi PCH, high(code$<$$<$1) 
    ldi PCL, low(code$<$$<$1)

   nextopcode:
    ; retrieve and save PC program counter 
    movw ZH:ZL, PCH:PCL     ; get ip 
    lpm opcode, Z+
    movw PCH:PCL, ZH:ZL     ; save ip 

   ; call digitx

   checkzero:
    ; halt if opcode is zero
    cpi opcode, 0 
    breq goodbye 

    ldi ZH, high(optable$<$$<$1) 
    ldi ZL, low(optable$<$$<$1)
    ;add ZL, r20    ; opcode number (need to double
    ;add ZL, r20    ; 
    ; double opcode because each address is 2 bytes 
    add ZL, opcode 
    adc ZH, zero
    add ZL, opcode 
    adc ZH, zero 
    
    lpm XL, Z+
    lpm XH, Z+
    movw ZH:ZL, XH:XL     ;  
    ijmp

    ; never executed I think
    ; jmp nextopcode

   goodbye:

    lds temp, UCSR0A     ; usart control, status register
    sbrs temp, UDRE0     ; is UDR empty?
    rjmp goodbye         ; if not, then just wait 
    ldi temp, '+'
    sts UDR0, temp       ; if empty tx character

   halt: 
     rjmp halt

   code:
     ; some bytecode to test the system, but the compiler will pad with zeros
     ; so be careful about jump targets if odd number of .dbs

     ; testing jumpnz
     ; .db STAR, STAR, KEY, DUP, EMIT, JUMPNZ, -5, 0
     ; print ascii table
     .db STAR, STAR
     .db KEY, DUP, EMIT, DECR, DUP, JUMPNZ, -4, DROP, JUMP, -10,  0

   ; word pointers to opcode functions. 
   optable:
     .dw 0, dupx, dropx, notx, incrx, decrx, emitx, keyx
     .dw jumpx, jumpnzx, fcallx, returnx, starx

   ; an example help header
   dups:
     .db "duplicate top stack item (16bit)", 0
     .dw dups 
   duph:
   dupx:
     push tosl      ; duplicate top stack item 
     push tosh      ; 
     jmp nextopcode 

   dropx:
     pop tosh      ; discard top of stack 
     pop tosl      ; 
     jmp nextopcode 

   ; logical negation of top of stack
   ; eg: tos $<$$>$ 0, tos $<$- 0 and tos==0, tos $<$- 1
   notx:
     sbiw tosh:tosl, 0
     breq notiszero 
     ldi tosh, 0 
     ldi tosl, 0
     jmp nextopcode 
   notiszero:
     ldi tosh, 0 
     ldi tosl, 1 
     jmp nextopcode 

   ; increments by 1 the top stack item
   incrx:
     adiw tosh:tosl, 1
     jmp nextopcode 

   ; decrement by 1 
   decrx:
     sbiw tosh:tosl, 1
     jmp nextopcode 

   emith:
    .dw dupx       ; the forth-style dictionary backlink
    .db 4, ``emit''  ; 
   emitx:
     waitagain:
     lds temp, UCSR0A      ; usart control, status register
     sbrs temp, UDRE0      ; is UDR empty?
     rjmp waitagain        ; if not, then just wait 
     sts UDR0, tosl        ; if empty tx character in TOS 
     pop tosh              ; high byte of TOS (should be zero)
     pop tosl              ; low byte of TOS 
     jmp nextopcode 
     
   keyh:
    .dw emitx 
    .db 3, ``key''
   keyx:
   waitkey:
     push tosl       ; low byte 
     push tosh       ; high byte
     lds temp, UCSR0A    ; get usart status info
     sbrs temp, RXC0     ; has a byte been received?
     rjmp waitkey        ; if not just wait for one.
     ldi tosh, 0         ; set high byte of TOS to 0
     lds tosl, udr0      ; get key char into low byte of TOS 
     jmp nextopcode 

   jumph:
   jumpx:
     movw ZH:ZL, PCH:PCL    ; get ip 
     lpm r16, Z             ; get jump
     ;just debug the digit
     ;mov r20, r16
     ;call digitx

     ; add or subtract jump offset from PC program counter  
     ; the code below is designed to sign extend from r16 to r17:r16 pair
     ; the idea is to make the subsequent addition or the program counter and offset
     ; work when the offset is negative (eg JUMP, -4)
     clr r17 
     sbrc r16,7 ; Skip if 8 bit value is positive
     com r17    ; 8 bit value is negative so set it's high byte
     ; or ser r17

     add PCL, r16 
     adc PCH, r17     ; add with carry

     ; since pch:pcl is "Y``, we can use sbiw ''subtract immediate from word"
     sbiw PCH:PCL, 1  ; adjust offset to JUMP instruction
     jmp nextopcode 

   ; a relative jump
   jumpnzx:
     movw XH:XL, TOSH:TOSL  ; save top of stack 
     pop tosh  
     pop tosl               ; drop top of stack
     sbiw XH:XL, 0          ; check if top of stack == 0
     breq nojump            ; if not update prog counter 
                            ; if == 0 jump to target
     movw ZH:ZL, PCH:PCL    ; get ip 
     lpm r16, Z             ; get jump
     clr r17 
     sbrc r16,7 ; Skip if 8 bit value is positive
     com r17    ; 8 bit value is negative so set it's high byte

     add PCL, r16 
     adc PCH, r17     ; add with carry

     ; since pch:pcl is "Y``, we can use sbiw ''subtract immediate from word"
     sbiw PCH:PCL, 1  ; adjust offset to JUMP instruction
     jmp nextopcode 

   nojump:
     adiw PCH:PCL, 1  ; skip over jump 
     jmp nextopcode 

   ; call a virtual proc and push the ret address onto the return stack
   ; untested!! need to check
   ; or make the ret stack grow towards high memory (ie toward top of 
   ; data stack) and check for a clash
   fcallx:
     adiw pch:pcl, 1
     ; push ret address onto ret stack
     movw XH:XL, rsh:rsl
     st X+, pcl
     st X+, pch
     movw rsh:rsl, xh:xl
     ; now adjust prog counter to jump
     sbiw pch:pcl, 1
     movw ZH:ZL, PCH:PCL    ; get ip 
     ld PCL, Z+             ; 
     ld PCH, Z+             ; 
     jmp nextopcode 

   returnx:
     ; todo write this
     ; just the reverse process for fcall. pop the ret address
     ; off the return stack and jump
     jmp nextopcode 

   starh:
    .dw keyx
    .db 4, ``star''
   starx:
    waithere:
     lds r16, UCSR0A       ; usart control, status register
     sbrs r16, UDRE0       ; is UDR empty?
     rjmp waithere         ; if not, then just wait 
     ldi r17, '*'    
     sts UDR0, r17         ; if empty tx next character
     jmp nextopcode 
     
   ; initialize an rs232 serial connection using onboard usart
   ; this cant really be used interactively so is not a forth-style command
   ; with header etc
   serialx:
     ldi r16, 1$<$$<$TXEN0 | 1$<$$<$RXEN0     ; enable transmit receive 
     sts UCSR0B, r16       
     ldi r16, 1$<$$<$UCSZ01 | 1$<$$<$UCSZ00
     sts UCSR0C, r16      
     ldi r16, 0x66    ; the baud rate, 9600 on 16 megaherz chip
     sts UBRR0L, r16
     ldi r16, 0x00    ; the baud rate, 9600
     sts UBRR0H, r16
     ret

   ; a primitive method of debugging 
   ; prints one digit in r20
   digitx:
     push r16
     push r17
   repeat:
     lds r16, UCSR0A    ; usart control, status register
     sbrs r16, UDRE0    ; is UDR empty?
     rjmp repeat        ; if not, then just wait 
     ldi r17, '0'       ; convert opcode to asci digit
     mov r16, r20       ; assumes 0 $<$ opcode $<$ 10
     add r16, r17
     sts UDR0, r16      ; if empty tx next character
     pop r17
     pop r16
     ret 

  ,,,

\section{Avr Assembly}

  Avr assembly is not case sensitive.

  Looking at the include file (for example m328Pdef.inc) can give some
  information about what bits to manipulate to configure, timers, interrupts
  etc.

\emph{ A so so avr assembly site }
\begin{lstlisting}
  https://sites.google.com/site/avrasmintro/
\end{lstlisting}

\subsection{Organisation}

  An avra assembly file has a standard format and organisation.
  Code should be able to be on the same line as a label, but a bug
  in the Mac OSX version of avra means that it cant.

\emph{ An example file with a reasonable organisation.  }
  -------
  .nolist
  ; the include file provides named registers for the given avr chip
  .include ``m328Pdef.inc''
  .list
  .eseg
    ; define eeprom data buffers here 
    ; There is 1024 bytes of eeprom in the atmega328 MCU
    ebuffer: 
      .db 5, ``hello'' 
  .dseg
    ; create data buffers here in sram
    counter:
      .byte 2
  .cseg
  .org 0
    jmp start
  .org 0x02      
    jmp  external0isr   ; external interrupt 0 vector 

    ; put interrupt service routines vectors here. 
    ; maybe create flash memory buffers here, or functions, or else put
    ; them at the end of the code. which maybe better because they dont
    ; get in the way of the ISR vector jumps.
  start:
    ; initialization code here.
    main:
      ; the main code loop here
      rjmp main
  
  ; procedures can go here
  sleep:
    ret

  ; Interrupt service routines.
  external0isr:
    ; service the interrupt.
    reti
  ,,,,


\subsection{Errors}

\begin{lstlisting}
  Error   : I/O out of range (0 <= P <= 63)
\end{lstlisting}
   This error may mean that you are trying to use OUT with 
   a memory mapped control register... Try usign STS instead!

\emph{ Use sts not out }
\begin{lstlisting}
  ; out TIMSK0, temp ; enable compare/match interrupt
\end{lstlisting}
\begin{lstlisting}
  sts TIMSK0, temp ; enable compare/match interrupt
\end{lstlisting}

\subsection{Tricks}
 
   define a register as null and then set it to zero.
  .def r2 = null

\subsection{Registers}

   r0 to r31 general purpose registers
   Z reg (r31:r30) 
     used for indirect addressing with lpm, icall and ijmp
     instructions. This is important in a byte code system.
   Y reg (r29:r28)
     indirect addressing of ram memory 
   X reg (r27:r26) 
     indirect addressing of ram memory 
   r25:r24
     could be used to hold top-of-stack in a 16 bit forth system
   r23:r22
     could be used for program counter PC

\subsection{Macros}

  Setting up the stack needs to be a macro and not a function
  because function calls with rcall etc, are not available until
  the stack pointer has been set!

\emph{ Macro example to set up the stack pointer  }
  \begin{lstlisting}
  .include "m328Pdef.inc"
    
  .macro initstack
    ldi r21,high(ramend)  
    out sph,r21        
    ldi r21,low(ramend)    
    out spl,r21        
  .endmacro
  
    initstack
  \end{lstlisting}

  
\subsection{Def}

  we can give registers more descriptive names with the .def
  assembler directive
   
\emph{ Eg }
  ---------
    .def acc = r0
    .def counter = r18 
  ,,,

\subsection{Labels}

  labels require a colon, eg buffer: not buffer
  labels cant start with dot (ie local labels in nasm)
  cant have dots in them...

\subsection{Constants}
   
\emph{ Define constants }
  \begin{lstlisting}
   .equ score = 100
   .set score = 100      ; the same but can be changed later
  \end{lstlisting}

\subsection{Data Segment}

  In the atmel avr architecture, code and data space are separate.

\emph{ Specify the data segment }
\begin{lstlisting}
  .dseg
\end{lstlisting}

\emph{ An example of creating a buffer in the data segment  }
  ---------
    .dseg
       counter: .byte 2
    .cseg

  ,,,,

\emph{ Copy from rom to ram }
  -----
    .nolist
    .include ``m328Pdef.inc''
    .list
    .def temp = r25
    .def counter = r24
    .dseg
      data:
      .byte 5  ; reserve 5 bytes (uninitialesed)
    .cseg
      sbi DDRB, 5    ; led on pin13
      cbi PORTB, 5   ; turn off the output pin  
      ldi ZL, low(romdata$<$$<$1)
      ldi ZH, high(romdata$<$$<$1)
      ldi XL, low(data)
      ldi XH, high(data)
      ldi counter, 5
      rcall copy
      rcall check
    halt:
      rjmp halt

    copy:
      lpm temp, Z+
      st X+, temp 
      dec counter 
      brne copy
      ret

    ; turn on the led if the buffer contains the letter
    check:
      ldi XL, low(data)
      ldi XH, high(data)
      ld temp, X
      cpi temp, 'a'
      brne endcheck
      ;sbi PINB, 5 ; apparently this toggles the led
      sbi PORTB, 5  ; turn on the output pin  
    endcheck:
      ret
    ; ...
    romdata: 
      .db ``aBCDE'' 

  ,,,

\subsection{Code Segment}

  With .db we can define string constants such as ``test'' but 
  without any escaped characters (eg \textbackslash n)

\emph{ Define some constant data in the code segment in flash memory }
  \begin{lstlisting}
  .include "m328Pdef.inc"
  .cseg
    greet:    .db "hello", 0
    greeting: .db "hello", '\n', 0
    message:  .db 'h','e','l','l','o',0  ; a harder way to do it
  \end{lstlisting}

\subsection{Mnemonics}

  avr assembly, as with all microcontroller assemblies has a plethora of
  mnemonics or aliases for referring to ports and registers.  Eg: tccr0b means
  "timer/counter 0 control register b". These are in addition to all the
  standard assembly mnemonics such as ``ldi'' etc.

\subsection{Arithmetic Instructions}

  These instructions perform some simple arithmetic on an 8 bit 
  register.

  add, sub, inc, dec


\subsection{Jumps}

  branches or jumps go to a particular instruction if the given condition is
  met. There are conditions which are specific to signed and unsigned numbers
  among others.

\emph{ Jump if reg16 is = or $>$ than 20 (unsigned comparison)  }
  ------
    cpi r16, 20
    brsh higher
    ; ...
  higher:

  ,,,


  \arrayrulecolor{gray}
  \begin{center}
  \begin{tabular}{ |rl| }
    \multicolumn{2}{c}{\textbf{ common signed branches }} \\
  \hline

  \texttt{ brge } & Branch if greater or equal, signed \\ 

  \texttt{ brlt } & Branch if less than, signed \\ 

  \texttt{ brpl } & If positive \\ 

  \texttt{ brmi } & If negative \\ 

    \hline
    \end{tabular}
    \end{center}

  \arrayrulecolor{gray}
  \begin{center}
  \begin{tabular}{ |rl| }
    \multicolumn{2}{c}{\textbf{ common unsigned branches }} \\
  \hline

  \texttt{ brlo } & Branch if less than \\ 

  \texttt{ brsh } & Branch if greater or equal \\ 

  \texttt{ brne  } & Branch if not equal \\ 

  \texttt{ breq  } & Branch if equal \\ 

    \hline
    \end{tabular}
    \end{center}
\subsection{Nop And Halting}

  There are various ways to halt or stop the uC. We can put it to sleep,
  enter and infinite loop etc

\emph{ An infinite loop that does nothing  }
  \begin{lstlisting}
   here: rjmp here
  \end{lstlisting}

\subsection{Skips}

  skips are similar to jumps except that they only skip one (the next)
  instruction, if the condition is met.

  sbic - ...

\subsection{Comparisons}

  In assembly comparisons may be unsigned or signed (since a given
  bit pattern in a register can be interpreted as either a signed 
  or unsigned number)

\emph{ Branch if less than (unsigned?) }
  ---
    cpi A, 200
    brlo under200
  ,,,,

\emph{ Compare a 16 bit value with an immediate value }
  -----
  compare16:	
    cpi r16, low(1234)	;Compare low byte
    ldi	r18, high(1234)	;
    cpc	r17, r18        ;Compare high byte
    ; the zero flag is set if equal
  ,,,,

  See Atmel application note AVR202 for 16bit comparisons

\emph{ Compare two 16 bit numbers for size }
  --------
  .include ``m328Pdef.inc''
  .cseg
    sbi DDRB, 5     ; make portB.5 output, arduino pin 13 (on-board led)
    ldi r17, 1 
    ldi r16, 0xFF   ; load 0x01FF into r17:r16
    ldi r19, 2 
    ldi r18, 0xFF
    cp r16, r18     ; compare low bytes
    cpc r17, r19    ; compare high bytes (with carry)
    brlo light
    rjmp here
  light:
    sbi PORTB, 5   ; turn on portB.5 (arduino pin13)
  here: 
    rjmp here
  ,,,


\subsection{Loops}

\emph{ The simplest loop construct }
  ----

    init:
      ldi r16, 100
    again:
      dec r16
      brne again 
  ,,,

\emph{ A delay loop }
  -------
  .include ``m328Pdef.inc''
  .cseg
  .org 0
    jmp start
    start:
      sbi DDRB, 5   ; make portb, 5 output (for the onboard led)
    again:
      sbi PORTB, 5 
      rcall sleep500
      cbi PORTB, 5 
      rcall sleep500
      rjmp start

    ; sleeps for approximately 500 milliseconds on a 16Mhz atmega328
    sleep500:
      clr r16           ; set reg16 := 0
      clr r17
      ldi r18, 42 
      here:             ; a delay loop 40*256\^{}2 instructions
        dec r16         ; 
        brne here 
        dec r17
        brne here 
        dec r18
        brne here 
      ret

   ,,,

\subsection{Procedures}

  call 
    is 4 bytes and can call anywhere in 64K
  rcall 
    is 2 bytes and can only call near proceedures
  icall 
    uses the Z register (r31:r30 register pair)
  ijmp
    is not a procedure call, but can be used like one


  both ``call'' and ``rcall'' put the same (absolute address) on
  the stack, so that ``ret'' works the same for both calls.

\subsection{Returning Values From A Function Or Procedure}

  The return value can be left on the stack, but it must be placed
  underneath the top value (which is the return address for the 
  procedure).

  Return values can just be left in a register

  A true/false return value could be indicated by setting or 
  clearing the carry flag with CLC or SEC.

\subsection{Using The Stack To Return A Value}

\emph{ Return a byte value on stack and juggle the return address.  }
  --------
    pop r31    ; high byte of ret address into ZH 
    pop r30    ; low byte of ret address in ZL
    push r24   ; put return value on stack
    push r30   ; restore return address, otherwise ``ret'' wont work!
    push r31
    ret        ; return to caller
  ,,,

  The technique below returns a byte value on the stack, and uses
  a trick to shorten 3 instructions into 1. It relies on the fact that
  the IJMP instruction jumps to the address in the Z (r31:r30) word register.

\emph{ Use a trick to return to caller after putting ret value on stack }
  --------
    pop r31    ; high byte of ret address into ZH 
    pop r30    ; low byte of ret address in ZL
    push r24   ; put return value on stack
    ijmp       ; return to caller (instead of ``push r30; push r31; ret;'')
  ,,,

\subsection{Return Value In Register}

  r25:r24 is a standard register pair for return values (not on the stack).
  But this is just a convention.
  
\subsection{Return Value In Carry Flag}

  The carry flag by convention is used to return a true/false value.

\subsection{Icall}

  Notice that loading the Z register for ICALL is different
  to loading the Z register for a table lookup with LPM.

\emph{ Call a procedure indirectly  }
  ----
  .include ``m328Pdef.inc''
  .cseg
     ldi zh, high(blink) 
     ldi zl, low(blink)
     icall
   here: jmp here

   blink:
     ret
  ,,,

  Code below not working, needs to be debugged.

\emph{ Call the 'blink' function indirectly (blink pin13 on arduino uno) }
  ----
  .include ``m328Pdef.inc''
  .cseg

     ;ldi r16,0b00100000
     ;out DDRB,r16   ; DDRB == data direction register B
     sbi ddrb, 5 
     ldi zh, high(blink) 
     ldi zl, low(blink)
   again:
     icall
     jmp again

   ; just does nothing for a while 
   sleep:
     clr r16             ; set reg16 := 0
     clr r17
     ldi r18, 40 
     here:              ; a delay loop 40*256\^{}2 instructions
       dec r16          ; 
       brne here 
       dec r17
       brne here 
       dec r18
       brne here 
     ret

   blink:
     sbi PORTB, 5 
     ;out PortB,r16  ; send a 'high' to PB5 only
     rcall sleep
     sbi PORTB, 5 
     rcall sleep
     ret

  ,,,

\subsection{Ijmp}

  Only the Z register can be used for indirect jumps. Post increment
  is not relevant here, or not useful.

\emph{ Jump to a procedure indirectly  }
  ----
  .include ``m328Pdef.inc''
  .cseg
     ldi zh, high(do) 
     ldi zl, low(do)
     ijmp

   here: jmp here

   do:
     sbi PORTB, 5 
     ;out PortB,r16  ; send a 'high' to PB5 only
     rcall sleep
     sbi PORTB, 5 
     rcall sleep
     ret
  ,,,

\subsection{Logical Instructions}

\subsection{Andi}

  andi - logical and with immediate (literal) value

\subsection{Eor}

  exclusive or. This can be used for toggling bits, but
  the operand cant be immediate. eg ``eor r20, 1'' is an error
  and won't be compiled

  another way to toggle might be to do 
  ----
    sbi ddrd, 5
    sbi pind, 5  ; apparently this toggles the led???
  ,,,

\emph{ Toggle the arduino pin 13 led with exclusive or }
  ---------

  .nolist
  .include ``m328Pdef.inc''
  .list
    .def mask = r16
  .cseg
  .org 0
    sbi DDRB, 5         ; portb.5 = output (for LED feedback) 
    ldi mask, 1$<$$<$5      ; toggle bit for portb,5
    eor r17, mask       ; xor toggle
    out PORTB, r17      ; 
    halt:
      rjmp halt
  ,,,,

   
\subsection{Bits}

\emph{ Toggle the least significant bit in r17 }
  \begin{lstlisting}
    eor r17, 1
    eor r17, 0x01    ; the same
  \end{lstlisting}

\emph{ Toggle the most significant bit in r17 }
  \begin{lstlisting}
    eor r17, 1<<8
    eor r17, 0b10000000      ; this is the same, but more verbose
  \end{lstlisting}

\section{Moving Data}

\emph{ Copy data from flash (``rom'' or ``program'') memory to sram data memory }
  \begin{lstlisting}
    .nolist
    ; change this to the avr chip in use.
    .include "tn2313def.inc"
    .list

      .def  temp  = r16	

    .DSEG
    .org 0
      test:  .byte 10  ; reserve space for array test[] in RAM				
    .CSEG
    .org 0
      rjmp start

    start:
      ldi   r16, ramend		; set stack pointer 	
      out   SPL, r16

    ;initialize test (copy test_init_values into test[])
       ldi   zl, low(test_init_values*2)   
       ldi   zh, high(test_init_values*2)   
       ldi   yl, low(test)   
       ldi   yh, high(test)   
       ldi   r17, 10          ; copy 10 bytes
       
    copy:
       lpm   temp, z+
       st    y+, temp
       dec   r17
       brne  copy    
    main:
       ldi   temp, 20
       sts   test+2, temp  ; test[2] = 20
       lds   temp, test+2  ; temp = test[2]
       rjmp main

    endmain:

    ;save init values in FLASH
    test_init_values:   .db  1,2,3,4,5,6,7,8,9,10 
    \end{lstlisting}

\subsection{Gotchas}

  If you use ``ld'' instead of ``lpm'' when reading rom (program memory)
  there will be no error, but you will probably just get zero (
  because you are actually reading sram data memory.)

  Also, there is no ``lpm r20, Y+'' instruction, must use Z or Z+

  Also, the minimum address for sram within the data segment
  (that is .dseg with .org) is 0x100 because addresses below that
  are registers and i/o ports....

\subsection{The Mac Bug With Avra}

  In some versions of avra on macosx you *must* use .org 0x100 or something
  similare at the top of the .dseg!!!!! Otherwise labels in the data segment
  dont work!.

  The bug appears to be the way that avra on macosx compiles 
  dseg labels. When I set the X reg pointer to a data segment 
  label with "ldi XH, high(buffer); ldi XL, low(buffer)" then
  the pointer is invalid. 

\emph{ The minimal code for the mac bug }
  -----
   .nolist
   .include ``m328Pdef.inc''
   .list
   .def temp = r16
   .def param = r17
   .dseg       
     ; must use .org 0x100 here otherwise dseg labels dont work on macosx avra
     .org 0x100
     ; sram data buffer, seems to be compiled incorrectly on
     ; mac osx
     input:    
      .byte 30
   .cseg

   ; initialize an rs232 serial connection using onboard usart
   serial:
     ldi r16, 1$<$$<$TXEN0 | 1$<$$<$RXEN0     ; enable transmit receive 
     sts UCSR0B, r16       
     ldi r16, 1$<$$<$UCSZ01 | 1$<$$<$UCSZ00
     sts UCSR0C, r16      
     ldi r16, 0x66    ; the baud rate, 9600 on 16 megaherz chip
     sts UBRR0L, r16
     ldi r16, 0x00    ; the baud rate, 9600
     sts UBRR0H, r16

   ; load X pointer with address of buffer
   ;ldi xh, high(input)   ; actually this seems to cause the problem
   ;ldi xl, low(input)    
   ldi xh, high(RAMEND-128)  
   ldi xl, low(RAMEND-128)    
   ldi r17, '!'  ; '!'=asci 33
   clr r18   ; used for the count loop
   nextchar:
   tx:
     lds temp, UCSR0A ; usart control, status register
     sbrs temp, UDRE0 ; is UDR empty?
     rjmp tx          ; if not, then just wait (block)
     ;ldi r17, 'a'
     st X, r17        ; the problem lines, r17 gets corrupted
     ld r17, X        ; because X pointer invalid if using high(input).
     sts UDR0, r17    ; if usart buffer empty tx character
     ; this prints '@', not 'a'
     ; in this case I think 6 lower bits are being zeroed
     inc r17
     cpi r17, 126   ; '$\sim$' is last printable char
     brne nextchar
   halt:
     rjmp halt

  ,,,,

\subsection{Pointers}

  The avr chips such as atmega328 have 3 register pairs xh:xl yh:yl zh:zl
  these can be used as 16bit registers with instructions like
  ``adiw'', ``sbiw'' etc. They can also be used as pointers.


  Pointers to code memory need to be put in the Z reg (ZH:ZL or r31:r30)
  Pointers to data memory can be in X,Y, or Z

  You need to double pointer reference when using lpm, but not icall!!
  see the forth ideas code section.

\emph{ Check if a pointer register pair is zero }
  -------
    sbiw XH:XL, 0
    breq exit       ; or brne to reverse the logic
    ; code if not zero
   exit:

  ,,,,

\emph{ Example  }
  ------
   .include ``m328Pdef.inc''
   .def temp = r0
   .cseg
     ldi ZH, high(pointer$<$$<$1)
     ldi ZL, low(pointer$<$$<$1)
     lpm YL, Z+    ; dereference the pointer in Z reg
     lpm YH, Z
     add YL, YL    ; need to double the pointer
     adc YH, YH    ; or lsl YH
     movw ZH:ZL, YH:YL
     ; now Z reg points to buffer for lpm
     ; but if you were using ``icall'' you would not need to double 
     ; the address bytes
     lpm temp, Z+
     ;etc 

   pointer: 
     .dw buffer
   buffer:
     .db ``text''

  ,,,

  If we write the pointer in an ugly way then

\emph{ Another way to write the pointer }
  -----
    .db low(typeh$<$$<$1), high(typeh$<$$<$1) 
  ,,,

\subsection{Table Read Instructions Lpm}

  Reading data from the code segment (flash memory) is often
  referred to as table reading. The code segment data is often
  assumed to be ``constant'' since it is not usually altered during
  the execution of a program (although it can be with the spm instructions)

  There is usually much more code memory (eg 32K in atmega328) than
  sram data memory (2K in atmega328) so it is a good idea to 
  store long strings here.

  lpm Rn, Z  - load program memory
  lpm Rn, Z+ - load program memory and increment pointer


\emph{ Read a string stored in the program memory  }
   ------
   .include ``m328Pdef.inc''
     .def counter = r16
   .dseg
   .cseg
   .org 0
     rjmp main
   buffer: 
     .db 5, ``hello''
   main:
     sbi DDRB, 5         ; portb.5 = output (for pin13 LED feedback) 
     ldi zh, high(buffer$<$$<$1) 
     ldi zl, low(buffer$<$$<$1)
     lpm counter, Z+     ; load string count into r16
   nextchar:
     cbi PORTB, 5    ; turn off led
     lpm r20, Z+     ; get contents of byte at z into r16 
     cpi r20, 'o' 
     brne continue 
     sbi PORTB, 5    ; turn on led if letter found
     rjmp halt 
   continue:
     dec counter 
     brne nextchar 
    
    halt: 
      rjmp halt
   ,,,


\subsection{In}
  
  in gets data from an i/o port

\subsection{Ldi}
  
  ldi - load immediate value 
  It is not possible to use ``ldi'' with the file registers below
  r16 (ie ``low registers''). But we can use CLR to load zero

\emph{ Load 5 in register 16 }
  \begin{lstlisting}
    ldi r16, 0b00000101   
  \end{lstlisting}

\emph{ Load 0 into register 3 }
  \begin{lstlisting}
    clr r3 
  \end{lstlisting}

\subsection{Mov}

  The mov instruction can be used for moving data with the 
  register file (r0 to r31) I think

\subsection{Indirect Addressing With Ld And St}

\emph{ Load contents of sram location 0x0130 into r18  }
   ------
   .include ``m328Pdef.inc''
   .eseg 
      ; define eeprom data buffers here 
      ; 1024 bytes of eeprom in atmega328
      ebuffer: 
        .db 5, ``hello'' 
   .dseg
      ; define sram data buffers here.
      ; 2k bytes of sram in atmega328
      dbuffer: 
        .byte 30
   .cseg
     ldi XL, 0x30
     ldi XH, 0x01
     ld r18, X

   here: 
     rjmp here         ; loop for ever
   ,,,

\emph{ Store 0 in 16 addresses starting at 0x0060  }
   ------
   .include ``m328Pdef.inc''

   .dseg
     buffer: 
       .byte 16

   .cseg
     ldi r16, 16
     ldi xl, 0x60
     ldi xh, 0x00
     ldi r20, 0x0
   again:
     st X+, r20
     dec r16
     brne again

   here: 
     rjmp here         ; loop for ever

   ,,,

\subsection{Sts}
 
  store direct to data space

\section{Arithmetic In Assembler}

\emph{ Increment odd numbers by one }
  -------
    sbrc r0,0   ; if lsb is 0 skip next increment instruction
    inc  r0     ; bit 0 was a 1 (number is odd), increase r0 by 1
  ,,,

\subsection{Signed Arithmetic}

 The description below shows how to add an 8bit register (interpreted as a signed number
 -128 to +127) to a 16bit register pair.

 Transform the 8-bit signed to 16 bit signed and then add the L.S.Bytes with carry and then add the carry (if exists)11, the 2 M.S. Bytes without the signs and put as sign the sign of the biggest. Beware there might be overflow.
 
\emph{ Add 8 bit signed register to 16bit register pair }
 ------
   clr 8bitvaluehighbyte ;New empty high byte for 8 bit value
   sbrc 8bitvaluelowbyte,7 ;Skip if 8 bit value is positive
   ser 8bitvaluehighbyte ;8 bit value is negative so set it's high byte
   ; or ``com ...'' for ones complement.
   add 16bitvaluelowbyte,8bitvaluelowbyte
   adc 16bitvaluehighbyte,8bitvaluehighbyte
 ,,,

\subsection{Division}

  There is no division instruction for the avr micros (attiny, atmega etc).
  Division can be coded with repeated subtraction but uses many clock cycles.
  Division by 2 or powers of two can be achieved easily with the LSR (logical
  shift right) instruction.

  The code for a simple 8 bit division is simple but can take a 
  few clocks.

\emph{ Divide 250 by 60  }
  \begin{lstlisting}
  .include "m328Pdef.inc"    ; the atmega328p, the usual arduino micro
     .def A = r16     ; an accumulator
     .def counter = r20
  .dseg       ; data in ram
  .cseg       ; code/data in rom
    ldi A, 250
    clr counter
  again:
    subi A, 60
    inc counter
    cpi A, 60
    brsh again
    ; the A register will have remainder and the counter will 
    ; have the dividend
    here: 
      rjmp here
  \end{lstlisting}

  unsigned??

\emph{ Divide 16bit value by 16bit value, repeated subtraction }
  \begin{lstlisting}
  .list
  .include "m328Pdef.inc"    ; the atmega328p, the usual arduino micro
  .nolist
     .def divl = r16     ; low byte of dividend 
     .def divh = r17     ; high byte of dividend 
     .def divisorl = r18
     .def divisorh = r19
     .def quotient = r20
     .equ D = 1000
     .equ dd = 100
  .cseg       ; code/data in rom
  .org 0
    ldi divl, low(D)
    ldi divh, high(D)
    ldi divisorl, low(dd)
    ldi divisorh, high(dd)

    clr quotient 
  again:
    sub divl, divisorl
    sbc divh, divisorh    
    inc quotient 
    ; check if divh:divl > divisorh:divisorl
    ; 16 bit comparison 
    cp divl, divisorl
    cpc divh, divisorh    
    brsh again 
  finished:
    ; the divh:divl register pair will have the remainder
    ; and register "quotient" (r20) will have the quotient
  main:
    sbi DDRB, 5         ; portb.5 = output (for LED feedback) 
    cbi PORTB, 5
    cpi quotient, 10 
    breq light
    rjmp here
  light:
    sbi PORTB, 5     ; turn on led if quotient is 10
    here: 
      rjmp here
  \end{lstlisting}

\emph{ Proceedure to divide 2 8bit numbers on the stack. }
  \begin{lstlisting}
  .include "m328Pdef.inc"    ; the atmega328p, the usual arduino micro
     .def A = r16     ; an accumulator
     .def divisor = r17
     .def counter = r20
     .def temp = r23
  .dseg       ; data in ram
  .cseg       ; code/data in rom
    rjmp main

   ; stack ( div divisor -- quotient remainder )
   divx:
     pop r21   ; juggle return address
     pop r22
     pop divisor
     pop A
     clr counter
   again:
     sub A, divisor
     inc counter
     cp A, divisor 
     brsh again
     push counter  ; quotient 
     push A        ; remainder
     push r22
     push r21
     ret
   main:
   
    ldi temp, 20   ; dividend 
    push temp 
    ldi temp, 4    ; divisor
    push temp 
    rcall divx
    ; quotient + remainder now on stack
    here: rjmp here
  \end{lstlisting}

\subsection{Division By Powers Of Two}

\emph{ Divide a 16 bit number (255) by 2 }
  \begin{lstlisting}
    ldi YH, 0x00
    ldi YL, 0xFF
    ; LSR on upper register, Logical shift right
    lsr YH
    ; ROR on the lower. Rotate right through carry
    ror YL
  \end{lstlisting}

\emph{ Multiply a 16 bit number (257) by 2 }
  \begin{lstlisting}
    ; LSL on lower register, Logical shift left
    ; ROL on the upper. Rotate left through carry
    ldi YH, 0x01
    ldi YL, 0x01
    lsl YL
    rol YH

    ; another way to double, just simple addition
    ; add YL, YL    
    ; adc YH, YH

  \end{lstlisting}


 
 
APPROXIMATE DIVISION ...

  An interesting text about simplified division by 10 and 5 which is
  accurate for 1 byte.
  https://www.avrfreaks.net/forum/dis-asm-dirty-math-tricks-adventures-division-ten

\emph{ Approximate division by 10 and 5 for an 8 bit argument }
  \begin{lstlisting}
  ; 8x8 division by ten, using a trick
  div10: 
    ldi b, 26
    mul a, b   ;answer in r1

  ; a longer version
  div10: 
    rcall div5  ;r1=a / 5
    lsr r1      ;r1=(a/5) / 2 = a/10
    ret

  div5: 
    ldi b,51 
    mul a,b 
    inc r1      ;answer in r1 
    ret
  \end{lstlisting}

\subsection{Multiplication}

  The avr ``mul'' instruction multiplies 2 arguments, each 1 byte 
  and leaves a 16 bit result in R1:R0. The multiplicand and multiplier
  can be any (high ?) register

\emph{ Multiply 42 by 10 leaving answer in r1:r0 }
  ---------
     ldi r16, 42      ;load multiplicand
     ldi r18, 10      ;load multiplier
     mul r16, r18     ;multiply contents of a and b
                      ;result 420 left in r1:r0 
  ,,,

\emph{ Testing mul  }
  -------
  .nolist
  .include ``m328Pdef.inc''
  .list
  .def multiplicand = r16
  .def multiplier = r17
  .cseg
  .org 0
    jmp start
  start:
    sbi DDRB, 5             ; make PORTB,bit 5 an output, onboard led
    ldi multiplicand, 42    ; 
    ldi multiplier, 10      ; 
    ; result in r1:r0
    mul multiplicand, multiplier  ;multiply contents of a and b
    ; move word to use cpi
    mov r20, r0
    mov r21, r1
    ; compare result to 420
    cpi r20, low(420)	;Compare low byte
    ldi	r18, high(420)	;
    cpc	r21, r18        ;Compare high byte
    brne off
  on:
    ; if equal turn on led
    sbi PORTB, 5
    rjmp continue
  off:
    cbi PORTB, 5
    ; if not turn off
  continue:
    rjmp continue
  ,,,,

\emph{ Multiplication by 10 without using ``mul'' }
  -----
    ; Bin1Mul10
    ; =========
    ; multiplies a 16-bit-binary by 10
    ; Sub used by: AscToBin2, Asc5ToBin2, Bcd5ToBin2
    ; In: 16-bit-binary in rBin1H:L
    ; Out: T-flag shows general result:
    ;   T=0: Valid result, 16-bit-binary in rBin1H:L ok
    ;   T=1: Overflow occurred, number too big
    ;
    Bin1Mul10:
      push rBin2H ; Save the register of 16-bit-binary 2
      push rBin2L
      mov rBin2H,rBin1H ; Copy the number
      mov rBin2L,rBin1L
      add rBin1L,rBin1L ; Multiply by 2
      adc rBin1H,rBin1H
      brcs Bin1Mul10b ; overflow, get out of here
    Bin1Mul10a:
      add rBin1L,rbin1L ; again multiply by 2 (4*number reached)
      adc rBin1H,rBin1H
      brcs Bin1Mul10b ; overflow, get out of here
      add rBin1L,rBin2L ; add the copied number (5*number reached)
      adc rBin1H,rBin2H
      brcs Bin1Mul10b ;overflow, get out of here
      add rBin1L,rBin1L ; again multiply by 2 (10*number reached)
      adc rBin1H,rBin1H
      brcc Bin1Mul10c ; no overflow occurred, don't set T-flag
    Bin1Mul10b:
      set ; an overflow occurred during multplication
    Bin1Mul10c:
      pop rBin2L ; Restore the registers of 16-bit-binary 2
      pop rBin2H
      ret
    ;
     
  ,,,

\subsection{Addition}

  There is no ADDI instruction, but there is a SUBI instruction
  but there is a trick 

\emph{ Add an immediate value 4 to register r16 }
\begin{lstlisting}
  subi r16, -4
\end{lstlisting}

\emph{ You can even sub a negative character in avra!! }
\begin{lstlisting}
  subi temp, -'0' ; add '0' (48) to temp
\end{lstlisting}

\subsection{Adding Two Byte Numbers}

  use addc.

\subsection{Converting Numbers To Ascii}

\emph{ Convert 3 digits to integer }
 -----
   .def ten = r16 
   .def temp = r19
   .def zero = r17
   .def counter = r18

   toInt:
     push counter ; save counter 
     ldi temp, 4 ; five chars, one too much
     mov counter, temp
     clr rBin1H ; Clear result
     clr rBin1L
     clt ; Clear T-Bit
   blankzero:
     dec counter    ; all chars read?
     breq finished  ; last char
     ld temp, Z+ ; read a char
     cpi temp, ' ' ; ignore blanks
     breq blankzero ; next char
     cpi temp, '0' ; ignore leading zeros
     breq blankzero ; next char
   nextchar:
     subi temp, '0'   ; 
     brcs invalidchar ; digit $<$ '0'
     cpi temp, 10     ; digit $>$ 9
     brcc invalidchar  
     ; here just use the normal 'mul' instruction.
     ; rcall Bin1Mul10  ; Multiply result by 10
     brts invalidchar ; Overflow occurred
     add rBin1L, temp ; add the digit
     ld temp, Z+
     brcc continue     ; no overflow to MSB
     inc rBin1H        ; Overflow to MSB
     breq invalidchar  ; Overflow of MSB
   continue:
     dec counter   ; downcount number of digits
     brne nextchar ; convert more chars
   finished: ; End of ASCII number reached ok
     sbiw ZL, 3    ; Restore start position of ASCII number
     pop counter   ; Restore register R0
     ; here put the 1 byte integer on the stack
     ret
   invalidchar:  ; Last char was invalid
     sbiw ZL, 1  ; Point to invalid char
     pop counter ; Restore register R0
     set ; Set T-Flag for error
     ret ; return with error condition set
         ; or put error on the stack
 ,,,,

\emph{ 5 digit ASCII to binary }
 --------
  
; Asc5ToBin2
; ==========
; converts a 5-digit ASCII to a 16-bit-binary
; In: Z points to first decimal ASCII-digit, leading
;   blanks and zeros are ok. Requires exact 5 digits.
; Result: T-Flag reports result:
;   T=0: result in rBin1H:rBin1L, valid, Z points to
;     first digit of the hex-ASCII-number
;   T=1: error, Z points to the first illegal character
;     or to the digit, where the overflow occurred
; Used registers: rBin1H:L (result), R0 (restored after
;   use), rBin2H:L (restored after use), rmp
; Called subroutines: Bin1Mul10
;

   Asc5ToBin2:
     push R0 ; R0 is used as counter, save it first
     ldi rmp,6 ; five chars, one too much
     mov R0,rmp
     clr rBin1H ; Clear result
     clr rBin1L
     clt ; Clear T-Bit
   Asc5ToBin2a:
     dec R0 ; all chars read?
     breq Asc5ToBin2d ; last char
     ld rmp,Z+ ; read a char
     cpi rmp,' ' ; ignore blanks
     breq Asc5ToBin2a ; next char
     cpi rmp,'0' ; ignore leading zeros
     breq Asc5ToBin2a ; next char
   Asc5ToBin2b:
     subi rmp,'0' ; treat digit
     brcs Asc5ToBin2e ; Last char was invalid
     cpi rmp,10 ; digit $>$ 9
     brcc Asc5ToBin2e ; Last char invalid
     rcall Bin1Mul10 ; Multiply result by 10
     brts Asc5ToBin2e ; Overflow occurred
     add rBin1L,rmp ; add the digit
     ld rmp,z+
     brcc Asc5ToBin2c ; no overflow to MSB
     inc rBin1H ; Overflow to MSB
     breq Asc5ToBin2e ; Overflow of MSB
   Asc5ToBin2c:
     dec R0 ; downcount number of digits
     brne Asc5ToBin2b ; convert more chars
   Asc5ToBin2d: ; End of ASCII number reached ok
     sbiw ZL,5 ; Restore start position of ASCII number
     pop R0 ; Restore register R0
     ret
   Asc5ToBin2e: ; Last char was invalid
     sbiw ZL,1 ; Point to invalid char
     pop R0 ; Restore register R0
     set ; Set T-Flag for error
     ret ; and return with error condition set

;

 ,,,

\section{Displaying Numbers}

  In any assembly language there is usually no immediately obvious
  way to display a number. This is always somewhat of a shock for a 
  high level programmer.  
  
  The usual strategy for displaying a number is to repeatedly 
  divide by the current base (10 for decimal, 16 for hexadecimal),
  keep the remainders from each division, and then display those
  remainders in reverse order (each remainder corresponds to one ``digit'')

  In the case of hexadecimal numbers we can use a lookup table to convert
  the remainder (0-15) to a displayable digit (0-F). Also, division by
  16 is considerably simpler than division by 10 in a microcontroller, 
  because division by 16 can be accomplished with a series of right 
  shifts of the number. Since most micros (including the avr chips) do not
  have a division opcode, division by 10 involves more hanky-panky.

  Because of this, our first attempt will be to display 1 byte in 
  hexadecimal.

\emph{ The procedure to display an integer }
  ----
    set display string = ""
    again: 
      divide by base.
      remainder is least significant digit.
      convert to ascii. append to beginning of display string
      if quotient = 0 break
      jump again
      print
  ,,,,

\subsection{Displaying Numbers In Decimal}
  
  This is a little more complicated than hexadecimal because of the 
  lack of a division opcode, but the conversion to a digit is 
  simpler because we just add '0' to the value to get the asci value.

  The process below is clever because it gets around the lack of a division
  instruction on the atmega328 uCs. If the number is just going to 
  be displayed/printed once, then we dont need to use 3 registers, just one.

\emph{ In pseudo code convert 8bit number to ascii base 10  }
  ----
  ; free 3 registers, 
  clr hundreds
  clr tens
  clr ones
  ldi temp, 0x30   ; convert to ascii 
  hundred:
    if $>$= 100
      inc hundreds 
      subi bin, 100
      loop hundred
    endif
    add hundreds, temp 
  ten:
    if $>$= 10
      inc tens
      subi bin, 10
      loop ten
    endif
    add tens, temp 
  one:
    if $>$= 1
      inc ones
      subi bin, 1
      loop one
    endif
    add ones, temp 
  
  ,,,


\emph{ Display 16 bit value in decimal without division }
  \begin{lstlisting}
   .nolist
   .include "m328Pdef.inc"    ; the atmega328p, the usual arduino micro
   .list

   .def digit = r16
   .def temp = r20       ; 
   .def paraml = r24      ; low byte of value to display 
   .def paramh = r25      ; high byte 

   .equ value = 62123 

   .dseg    ; ram data segment 
   .cseg    ; rom program memory (flash)
   .org 0
   jmp start
   start:
     ; assume auto init stack
     rcall serial
     ldi digit, '['
     rcall emit

     ldi paramh, high(value)
     ldi paraml, low(value)
     rcall printdecword

     ldi digit, ']'
     rcall emit
   halt: 
      rjmp halt

   ; initialize an rs232 serial connection using onboard usart
   serial:
     ldi temp, 1<<TXEN0 | 1<<RXEN0     ; enable transmit receive 
     sts UCSR0B, temp
     ldi temp, 1<<UCSZ01 | 1<<UCSZ00   ; parity, bits etc
     sts UCSR0C, temp
     ldi temp, 0x66    ; the baud rate, 9600 on 16 megaherz chip
     sts UBRR0L, temp
     ldi temp, 0x00    ; the baud rate, 9600
     sts UBRR0H, temp
     ret

   ; transmit 1 character in "digit" reg over serial connection
   emit:
   transmit:
     lds temp, UCSR0A ; usart control, status register
     sbrs temp, UDRE0 ; is UDR empty?
     rjmp transmit    ; if not, then just wait (block)
     sts UDR0, digit  ; if empty tx character
     ret

   ; print the 16 bit value in paramh:paraml to serial as an unsigned decimal number
   ; the code below is verbose and cant handle negatives but seems to work well.
   printdecword: 
     ; 16 value to print is in paramh:paraml
     clr digit  
   tenthousands:
     ; if >= 10000
     cpi paraml, low(10000)   ; compare low byte
     ldi temp, high(10000)
     cpc paramh, temp        ; compare high byte
     brlo notenthousands
     inc digit
     subi paraml, low(10000)
     ldi temp, high(10000)
     sbc paramh, temp     ; 16bit subtraction
     rjmp tenthousands
   notenthousands:
     subi digit, -'0'
     rcall emit 
     clr digit  
   thousands:
     ; if >= 1000
     cpi paraml, low(1000)   ; compare low byte
     ldi temp, high(1000)
     cpc paramh, temp        ; compare high byte
     brlo nothousands
     inc digit
     subi paraml, low(1000)
     ldi temp, high(1000)
     sbc paramh, temp     ; 16bit subtraction
     rjmp thousands
   nothousands:
     subi digit, -'0'
     rcall emit 
     clr digit  
   hundreds:
     ; if >= 100
     cpi paraml, 100
     brlo nohundreds 
     inc digit
     subi paraml, 100
     rjmp hundreds
   nohundreds:
     subi digit, -'0'
     rcall emit 
     clr digit  
   tens:
     ; if >= 10
     cpi paraml, 10
     brlo notens
     inc digit
     subi paraml, 10
     rjmp tens 
   notens:
     subi digit, -'0' ; convert to ascii
     rcall emit       ; print the digit
     clr digit  
   ones:
     ; if >= 1
     cpi paraml, 1
     brlo noones
     inc digit
     subi paraml, 1
     rjmp ones
   noones:
     subi digit, -'0' ; convert to ascii
     rcall emit  ; print the digit
     ret         ; cant use ijmp because "emit" changes Z reg

  \end{lstlisting}

\emph{ Display one byte in decimal without division }
  \begin{lstlisting}
   ; working 19 april 2020
   .nolist
   .include "m328Pdef.inc"    ; the atmega328p, the usual arduino micro
   .list

   .def temp = r20       ; 
   .def param = r24      ; used for local parameters

   .dseg    ; ram data segment 
   .cseg    ; rom program memory (flash)
   .org 0
   jmp start
   start:

     ; initialise the stack at the top of ram
     ldi r21, high(ramend)  
     out sph, r21        
     ldi r21, low(ramend)    
     out spl, r21        

     ; test emit
     rcall serial
     ldi temp, '['
     push temp 
     rcall emit

     ldi temp, 234
     push temp
     rcall printdec

     ldi temp, ']'
     push temp 
     rcall emit
   here: 
       rjmp here 

   ; initialize an rs232 serial connection using onboard usart
   serial:
     ldi r16, 1<<TXEN0 | 1<<RXEN0     ; enable transmit receive 
     sts UCSR0B, r16       
     ldi r16, 1<<UCSZ01 | 1<<UCSZ00
     sts UCSR0C, r16      
     ldi r16, 0x66    ; the baud rate, 9600 on 16 megaherz chip
     sts UBRR0L, r16
     ldi r16, 0x00    ; the baud rate, 9600
     sts UBRR0H, r16
     ret

   ; using the stack to pass parameters is like a protocol
   ; transmit 1 character in r17 over serial connection
   emit:

   transmit:
     lds temp, UCSR0A ; usart control, status register
     sbrs temp, UDRE0 ; is UDR empty?
     rjmp transmit    ; if not, then just wait (block)
     pop ZH    ; high byte of ret address into r31
     pop ZL    ; low byte of ret address in r30 
     pop temp  ; get character to transmit 
     sts UDR0, temp  ; if empty tx character
     ijmp            ; return to caller (return address already in Z reg)

   ; print the 8 bit value on stack to serial as an unsigned decimal number
   .def digit = r16
   printdec: 
     pop ZH    ; high byte of ret address into r31
     pop ZL    ; low byte of ret address in r30 
     pop param ; get 8bit integer to print 
     push ZL   ; save the return address on the stack
     push ZH   ; 
     ; use the pseudo code above with only one reg

     clr digit  
   hundreds:
     ; if >= 100
     cpi param, 100
     brlo nohundreds 
     inc digit
     subi param, 100
     rjmp hundreds
   nohundreds:
     subi digit, -'0'
     push digit
     ; function "emit" does not use "param" register, 
     ; so we do not have to preserve it on the stack
     rcall emit 
     clr digit  
   tens:
     ; if >= 10
     cpi param, 10
     brlo notens
     inc digit
     subi param, 10
     rjmp tens 
   notens:
     subi digit, -'0' ; convert to ascii
     push digit
     rcall emit       ; print the digit
     clr digit  
   ones:
     ; if >= 1
     cpi param, 1
     brlo noones
     inc digit
     subi param, 1
     rjmp ones
   noones:
     subi digit, -'0' ; convert to ascii
     push digit
     rcall emit  ; print the digit
     ret         ; cant use ijmp because "emit" changes Z reg

  \end{lstlisting}

\subsection{Displaying Numbers In Binary}

  incomplete.

  The procedure for displaying a number in binary is also a general
  procedure for displaying a number in any base. See algorithm above
  We can also display binary numbers with a series of on/off leds,
  or even a series of blinks of a single led.

\emph{ Display an 8 bit register in binary over a serial connection }
  --------
  .nolist
  .include ``m328Pdef.inc''    ; the atmega328, the usual arduino micro
  .list

    .def temp = r18
    .def counter = r22
  .dseg

    ; this buffer will hold the binary display string.
    display: .byte 20

  .cseg
   ; start of flash ``rom'' code segment
   .org 0x0000
   jmp start
 start:
    ; assume stack auto initialised 

    rcall serialx    ; set up serial interface
    ldi r16, 9 
    rcall printbin
    ldi r16, 12 
    rcall printbin

  main: 
     rjmp main 

   ; another strategy would be to do ``lsl'' and save the most significant
   ; bit in the carry flag, then print it. This saves having to reverse
   ; the order of the digits. But it is not a general base procedure.

   ; print an 8 bit number in r16 register in binary format
   printbin:
     ldi counter, 8
   next:
     ; incomplete!!
     mov temp, r16
     ; divide by two. append to string ``display''
     lsr temp        ; temp = int(temp/2)
     ; convert the 1/0 to ascii
     subi temp, -'0' ; add '0' to temp
     dec counter
     brne next
     ret

   ; initialize an rs232 serial connection using onboard usart
   serialx:
     ldi r16, 1$<$$<$TXEN0 | 1$<$$<$RXEN0     ; enable transmit receive 
     sts UCSR0B, r16       
     ldi r16, 1$<$$<$UCSZ01 | 1$<$$<$UCSZ00
     sts UCSR0C, r16      
     ldi r16, 0x66    ; the baud rate, 9600 on 16 megaherz chip
     sts UBRR0L, r16
     ldi r16, 0x00    ; the baud rate, 9600
     sts UBRR0H, r16
     ret

   ; transmit 1 character in r17 over serial connection
   emitx:
    transmit:
     lds temp, UCSR0A    ; usart control, status register
     sbrs temp, UDRE0    ; is UDR empty? (usart data register empty?)
     rjmp transmit       ; if not, then just wait 
     sts UDR0, r17       ; if empty tx next character
     ret
     
  ,,,

\subsection{Displaying Numbers In Hexadecimal}
  
  Another technique is to add '0' or 'A' ? to the value to get
  a displayable digit. So we dont have to do any table lookup.

\emph{ Display an 8 bit and 16bit values in hexadecimal with no lookup table }
  --------
  ; 8 bit and 16bit working 2020
  .nolist
  .include ``m328Pdef.inc''    ; the atmega328, the usual arduino micro
  .list
    .def temp = r17
    .def char = r18
    .def counter = r22
    .def param = r23
    .def paraml = r24
    .def paramh = r25

    .equ value = 0xAB12

  .cseg
  .org 0
    rjmp start
  start:
   
    ; assume auto initialise stack pointer 

    rcall serialx    ; set up serial interface
    ldi param, 0xFA 
    rcall printhex
    ldi char, ' '
    rcall emitx
    ldi paramh, high(value) 
    ldi paraml, low(value) 
    rcall printhexword

    halt: 
     rjmp halt

   ; prints the hex value in paramh:paraml 
   printhexword:
     mov param, paramh
     rcall printhex
     mov param, paraml
     rcall printhex
     ret

   ; prints the byte in ``temp'' in hex with no lookup table 
   ; 13 instructions
   printhex:
     ldi counter, 2
   next:
     swap param       ; print high nibble digit first, low 2nd
     mov temp, param 
     andi temp, 0x0F  ; remove high nibble in temp
     cpi temp, 10
     brlo nothex
     subi temp, -7   ; Hex digit so add 8 to get ABCDEF 
   nothex:
     subi temp, -'0' ; add '0' to temp
     mov char, temp
     rcall emitx
     dec counter
     brne next
     ret

   ; initialize an rs232 serial connection using onboard usart
   serialx:
     ldi temp, 1$<$$<$txen0 | 1$<$$<$rxen0     ; enable transmit receive 
     sts UCSR0B, temp
     ldi temp, 1$<$$<$ucsz01 | 1$<$$<$ucsz00
     sts UCSR0C, temp
     ldi r16, 0x66    ; the baud rate, 9600 on 16 megaherz chip
     sts UBRR0L, r16
     ldi r16, 0x00    ; the baud rate, 9600
     sts UBRR0H, r16
     ret

   ; transmit 1 character in r17 over serial connection
   emitx:
    transmit:
     lds temp, UCSR0A    ; usart control, status register
     sbrs temp, UDRE0    ; is UDR empty? (usart data register empty?)
     rjmp transmit       ; if not, then just wait 
     sts UDR0, char      ; if empty tx next character
     ret
     
  ,,,

\emph{ Display an 8 bit register in hexadecimal using a lookup table }
  --------
  .include ``m328Pdef.inc''    ; the atmega328, the usual arduino micro

    .def temp = r18
    .def counter = r22
  .cseg
   ; start of flash ``rom'' code segment
   .org 0x0000
   jmp wakeup
   
   ; a hex digit lookup table
   hextable: 
     .db ``0123456789ABCDEF''

   ; prints the byte in r16 in hex over a serial connection 
   ; the printhex2 below is more succinct and doesnt require
   ; a lookup table.
   printhex:
     ldi counter, 2
     clr r2
   nextnibble:
     swap r16
     ldi ZH, high(hextable$<$$<$1) 
     ldi ZL, low(hextable$<$$<$1)
     mov temp, r16       
     andi temp, 0x0F  ; remove high nibble in r18 
     add zl, temp     ; get digit by offset
     adc zh, r2       ; propagate carry bit 
     lpm r17, Z       ; load hex digit from table
     rcall emitx
     dec counter
     brne nextnibble
     ret

   ; initialize an rs232 serial connection using onboard usart
   serialx:
     ldi r16, (1$<$$<$txen0)|(1$<$$<$rxen0)     ; enable transmit receive 
     sts UCSR0B, r16       
     ldi r16, (1$<$$<$ucsz01)|(1$<$$<$ucsz00)
     sts UCSR0C, r16      
     ldi r16, 0x66    ; the baud rate, 9600 on 16 megaherz chip
     sts UBRR0L, r16
     ldi r16, 0x00    ; the baud rate, 9600
     sts UBRR0H, r16
     ret

   ; transmit 1 character in r17 over serial connection
   emitx:
    transmit:
     lds temp, UCSR0A    ; usart control, status register
     sbrs temp, UDRE0    ; is UDR empty? (usart data register empty?)
     rjmp transmit       ; if not, then just wait 
     sts UDR0, r17       ; if empty tx next character
     ret
     
   wakeup:
    ; initialise the stack at the top of ram
    ldi r21, high(ramend)  
    out sph, r21        
    ldi r21, low(ramend)    
    out spl, r21        
   
    rcall serialx    ; set up serial interface
    ldi r16, 0xFA 
    rcall printhex2
    ldi r16, 0x3B 
    rcall printhex2

    halt: 
     rjmp halt
  ,,,


\section{Strings}

  It appears that avra doesnt support special chars such as \textbackslash n

\emph{ Define some ``constant'' strings in the code segment }
  \begin{lstlisting}
  .include "m328Pdef.inc"
  .cseg
    greet: .db "hello", 0
    message: .db 'h','e','l','l','o',0  ; a harder way to do it
  \end{lstlisting}

\emph{ Create a 20 byte string buffer in the data segment (sram)  }
  \begin{lstlisting}
  .include "m328Pdef.inc"
  .dseg
    input: .byte 20 
  .cseg
    greet: .db "hello", 0
  \end{lstlisting}

\section{Memory}

  The atmega328 (the original ``arduino'' micro-controller) is designed
  with a ``harvard'' architecture. This may be unfamiliar for programmers 
  coming from an Intel x86 environment (which is a ``Von Neuman'' architecture).

  Perhaps the main feature of the harvard architecture is the separation of 
  program and data memory. These 2 types of memory have very different 
  characteristics and different instructions for reading and writing them.

\subsection{Eeprom Memory}

  eeprom is rewritable memory that is conserved when there is no power to the
  uC. I think it can be initialised in the .eseg section. The atmega328P has
  1024 bytes of eeprom. 

\emph{ Write to eeprom }
  --------
      ;Put 1 byte in r16 to address pointed by Z.
      put\_ieep\_byte:
      sbic    EECR,EEWE                       ; Wait for completion of previous write
      rjmp    put\_ieep\_byte
      out     EEARH,zh                        ; Set up address (in Z ) in address register
      out     EEARL,zl
      out     EEDR,r16                        ; Write data (r16) to data register
      sbi     EECR,EEMWE                      ; Write logical one to EEMWE
      sbi     EECR,EEWE                       ; Start eeprom write by setting EEWE
      ret
  ,,,,


\subsection{Flash Program Memory}
  
  Flash memory is also known as ``rom'' (or read-only) memory, although 
  this memory can be written to using the avr SPM instruction. However
  there are a number of hurdles to overcome in writing to flash memory.
  The program code is stored in this memory.

  In the Atmega328 there is 32K of flash memory (hence the ``32'' in the 
  chip name) as opposed to only 8K of data memory (hence the "8" in the 
  chip name).
  
  We can read from the atmega flash memory using the LPM (load program memory)
  instruction.

  The code below can't be run because it doesnt have any way to 
  receive the string into sram.

\emph{ Compare a string in flash memory to a string in sram }
  ------
    .nolist
    .include ``m328Pdef.inc''
    .list
      .def  temp  = r16	
    .DSEG
      test: 
        .byte 10  ; reserve space for array test[] in RAM				
    .CSEG
      .org 0
      rjmp start

    start:

      ldi zl, low(2*buffer) ; Set a pointer to the table in program memory
      ldi zh, high(2*buffer);
      ldi yl, low(test)   ; Set a pointer to the table in RAM
      ldi yh, high(test)
      rcall compare
      brcs ledoff          
    ledon:
      ; turn on the led if strings are the same.
      rjmp start
    ledoff:
      ; turn on the led if strings are the not the same
      rjmp start

    ; compare zero terminated strings in sram and flash
    compare:
      loop: 
        ld r16, Y+          ; Get byte character from RAM
        lpm r0, Z+          ; and from FLASH
        ; Z+ is better no?  ; adiw r30:r31,1;
        cp r16, r0    ; Compare bytes
        brne notequal ; Branch if not equal
        tst r16       ; At the end of string
        brne loop     ; Branch if NO
        clc           ; Clear carry flag to mark comparison succes
        ret           ; return from function
      notequal: 
        sec           ; Set carry flag in case of not equal strings
        ret

    buffer: 
      .db ``cewek'', 0

   ,,,

\emph{ Receive characters via rs232 and compare to a string in flash  }
  ------
    .nolist
    .include ``m328Pdef.inc''
    .list
      ; define register names just for readability
      .def temp  = r16	
      .def counter = r20 
    .DSEG
      test: 
        .byte 10  ; reserve space for array test[] in SRAM				
    .CSEG
      .org 0
      rjmp start

    start:
      ; initializing the stack pointer is normally not necessary.
      sbi DDRB, 5   ; make PORTB,bit 5 an output 
      ldi YL, low(test)   ; Set a pointer to the table in RAM
      ldi YH, high(test)
      rcall serial

      rcall key     ; get key value into r17
      st Y+, r17
      rcall emit
      rcall key
      st Y+, r17
      rcall emit
      ldi zl, low(2*buffer) ; Set a pointer to the table in program memory
      ldi zh, high(2*buffer);
      ldi yl, low(test)   ; Set a pointer to the table in RAM
      ldi yh, high(test)
      rcall compare       ; check if strings equal, result in carry flag
      brcs ledoff          
    ledon:
      ; turn on the led if strings are the same.
      sbi PORTB, 5  
      rjmp start
    ledoff:
      ; turn off the led if strings are the not the same
      sbi PORTB, 5  
      rjmp start

    ; compare zero terminated strings in sram and flash
    compare:
      loop: 
        ld r16, Y+          ; Get byte character from RAM
        lpm r0, Z+          ; and from FLASH
        ; Z+ is better no?  ; adiw r30:r31,1;
        cp r16, r0    ; Compare bytes
        brne notequal ; Branch if not equal
        tst r16       ; At the end of string
        brne loop     ; Branch if NO
        clc           ; Clear carry flag to mark comparison succes
        ret           ; return from function
      notequal: 
        sec           ; Set carry flag in case of not equal strings
        ret

   ; emit the character in r17 register.
   emit:
     waitagain:
     lds r16, UCSR0A       ; usart control, status register
     sbrs r16, UDRE0       ; is UDR empty?
     rjmp waitagain        ; if not, then just wait 
     sts UDR0, r17         ; if empty tx character
     ret
     
   ; receive a keystroke into the r17 register. 
   key:
   wait:
     lds r16, UCSR0A    ; get usart status info
     sbrs r16, RXC0     ; has a byte been received?
     rjmp wait          ; if not just wait for one.
     lds r17, UDR0      ; get received byte
     ret

   serial:
     ldi r16,(1$<$$<$txen0)|(1$<$$<$rxen0)     ; enable transmit receive 
     sts UCSR0B, r16       
     ldi r16,(1$<$$<$ucsz01)|(1$<$$<$ucsz00)
     sts UCSR0C, r16      
     ldi r16,0x66    ; the baud rate, 9600 on 16 megaherz chip
     sts UBRR0L,r16
     ldi r16,0x00    ; the baud rate, 9600
     sts UBRR0H,r16
     ret

   buffer: 
      .db ``ce'', 0

   ,,,

  In c structures can be put in Flash with the PROGMEM statement.

\subsection{Sram Data Memory}

  There is 8K of sram data memory in the atmega328. It is simple to both 
  read and write to this type of memory an unlimited amount of times.

\section{Serial Interface}

  The avr atmega chips have a serial uart interface.  This needs to be
  configured to a certain baud rate, parity and stop bit. The serial interface
  is very useful for communicating with the atmega from a computer, since the
  standard arduino usb connection can be treated as a serial connection. Also,
  in a forth-style system the serial connection is used to issue commands and
  ``program'' the chip. 

  By combining these techniques with and hc05 bluetooth chip we have 
  a simple way to wirelessly control and program an arduino.

\emph{ Formula for value of ubrr register }
\begin{lstlisting}
  #define ubrr (FOSC/(16*BAUD))-1 
\end{lstlisting}
  
\subsection{Gotchas}

 If you see the backtick ` coming back from a serial terminal, then 
 this seems to indicate a stack overflow for some reason .....

 If you cant see the correct device in /dev/tty* it is probably because
 the usb cable is Not a data cable!.
 
\subsection{Serial Terminals}

  A serial terminal is a program which runs on a computer which allows 
  us to communicate via rs232 with an arduino board that is connected in
  some way via serial. However, both USB and Bluetooth serial can also
  be used. This is very useful for testing programs and seeing what is 
  actually happening on the MCU as the code is running.

  minicom, picocom, microcom, cutecom (easiest, graphical)
  If gibberish is returned from arduino, check that baud rates match.

  I used picocom because it seems to run well from the command line
  on mac osx and linux.

\subsection{Repl Loop With Serial}

  For example, change the frequency of a tone sent to a piezo speaker
  or a flashing led.

  The code below is a simple model for receiving single keypress commands
  over a serial connection and performing an action for each keypress.

\emph{ Turn on or off the onboard led depending on the key pressed  }
  ------
  .nolist
  .include ``m328Pdef.inc''
  .list

   .dseg
   ; ram data segment 
   .cseg
   ; start of flash ``rom'' code segment

   .org 0

   jmp start
   ; put isr vectors here

   ; receive a keystroke into the r17 register. 
   key:
   wait:
     lds r16, UCSR0A    ; get usart status info
     sbrs r16, RXC0     ; has a byte been received?
     rjmp wait          ; if not just wait for one.
     lds r17, udr0      ; get received byte
     ret

   serial:
     ldi r16, 0 | 1$<$$<$txen0 | 1$<$$<$rxen0     ; enable transmit receive 
     sts UCSR0B, r16       
     ldi r16, 1$<$$<$ucsz01 | 1$<$$<$ucsz00 
     sts UCSR0C, r16      
     ldi r16, 0x66    ; the baud rate, 9600 on 16 megaherz chip
     sts UBRR0L, r16
     ldi r16, 0x00    ; the baud rate, 9600
     sts UBRR0H, r16
     ret

   start:
    ; initialise the stack at the top of ram
    ldi r21, high(ramend)  
    out SPH, r21        
    ldi r21, low(ramend)    
    out SPL, r21        
   
    call serial   ; set up serial interface
    sbi DDRB, 5   ; make PORTB,bit 5 an output 

   ; the main program loop
   again:
     call key
     cpi r17, 'a'  ; compare immediate
     breq ledon    ; branch if r17 == 'a' 
     cpi r17, 'b'  ; compare immediate
     breq ledoff   ; 'b' was pressed 
     rjmp again
    
   ; handle keypresses here.
   ledon:
     sbi portb, 5  ; turn on the output pin  
     rjmp again
   ledoff:
     cbi portb, 5  ; turn off the output pin  
     rjmp again
  ,,,

\emph{ Receive a keystroke over serial and handle specific keypresses }
  ------
  .include ``m328Pdef.inc''

   .dseg
   ; ram data segment 
   .cseg
   ; start of flash ``rom'' code segment

   .org 0x0000

   jmp wakeup

   ; emit the character in r17 register.
   emit:
     waitagain:
     lds r16, UCSR0A       ; usart control, status register
     sbrs r16, UDRE0       ; is UDR empty?
     rjmp waitagain        ; if not, then just wait 
     sts UDR0, r17         ; if empty tx character
     ret
     
   ; receive a keystroke into the r17 register. 
   key:
   wait:
     lds r16, UCSR0A    ; get usart status info
     sbrs r16, RXC0     ; has a byte been received?
     rjmp wait          ; if not just wait for one.
     lds r17, udr0      ; get received byte
     ret

   serial:
     ldi r16,(1$<$$<$txen0)|(1$<$$<$rxen0)     ; enable transmit receive 
     sts ucsr0b, r16       
     ldi r16,(1$<$$<$ucsz01)|(1$<$$<$ucsz00)
     sts ucsr0c, r16      
     ldi r16,0x66    ; the baud rate, 9600 on 16 megaherz chip
     sts ubrr0l,r16
     ldi r16,0x00    ; the baud rate, 9600
     sts ubrr0h,r16
     ret

   wakeup:
    ; initialise the stack at the top of ram
    ldi r21, high(ramend)  
    out sph, r21        
    ldi r21, low(ramend)    
    out spl, r21        
   
    call serial    ; set up serial interface

   ; the main program loop
   again:
     ldi r17, '*'    
     call emit
     call key
     cpi r17, 'a'  ; compare immediate
     breq apressed ; branch if r17 == 'a' 
     cpi r17, 'b'  ; compare immediate
     breq bpressed ; branch if r17 == 'b' 
     call emit
     rjmp again
    
   ; handle keypresses here.
   apressed:
     ldi r17, 'A'    
     call emit
     rjmp again
   bpressed:
     ldi r17, 'B'    
     call emit
     rjmp again

  ,,,

  Now we can develop the code above to change the fequency of a tone
  when a key is pressed.

\subsection{Serial Communication In C}
  
  The serial interface is a great way to get information from an arduino
  about what it is doing or feeling. You can get this over the usb interface
  to the computer or via an hc05 bluetooth component for ``remote'' boards.
  Make sure the ``baud'' rate is the same on the serial monitor and
  in the sketch.
  
\begin{lstlisting}
  Serial.begin(9600);  
\end{lstlisting}
     baud rate is 9600. Serial monitor has to be the same or else
     gibberish is shown. Also make sure line endings are NL \& CR

  serial.write() etc


\emph{ Basic sketch with serial  }
  \begin{lstlisting}
   void setup()            
   {
     Serial.begin(9600);  
     Serial.println("Hello !!!"); 
   }

   void loop()      
   {
     
   }

  \end{lstlisting}
                   
\emph{ Read one char from serial port and do something with it }
  \begin{lstlisting}
   void loop() {
     static int v = 0;
     if (Serial.available()) {
       char ch = Serial.read();
       switch(ch) {
       case '0'...'9':
         v = ch - '0';
         Serial.print("To position:");
         Serial.println(v);
         break;
       case 's':
         break;
       case 'w':
         break;
       }
     }
     //Servo::refresh();
   }
  \end{lstlisting}

\subsection{Transmitting}

  By removing umsel0 code something positive happened. the little
  yellow tx light on the arduino uno lit up. good. wow its 
  finally working, printing out yes yes yes the whole time. nice
  
  To test, open a serial terminal with device /dev/ttyACM0 or 
  something similar and select baud 9600. See the vim section for a 
  macro to run the 'picocom' serial monitor to test this code.

\emph{ Transmit a digit using usart  }
  \begin{lstlisting}
  .include "m328Pdef.inc"
    
  .cseg
    
    ; initialise the stack at the top of ram
    ldi r21,high(ramend)  
    out sph,r21        
    ldi r21,low(ramend)    
    out spl,r21        
  
    ; initialise the rs232 serial connection
    ldi r16,(1<<TXEN0)     ; enable transmit  
    sts UCSR0B, r16       
    ldi r16,(1<<UCSZ01)|(1<<UCSZ00)
    sts UCSR0C, r16      
    ldi r16,0x66    ; the baud rate, 9600 on 16 megaherz chip
    sts UBRR0L,r16
    ldi r16,0x00    ; the baud rate, 9600
    sts UBRR0H,r16
  
    ldi r17, 4
    rcall txdigit

  here: rjmp here

  txdigit:
    lds r16, UCSR0A     ; usart control, status register
    sbrs r16, UDRE0     ; is usart data register empty?
    rjmp txdigit        ; if not, then just wait 
    ldi r18, '0'        ; convert digit in r17 to an asci character
    add r17, r18        ; 
    sts UDR0,r17        ; if empty tx the digit 
    ret
  \end{lstlisting}

\emph{ Transmit using the usart serial interface }
  \begin{lstlisting}
  .include "m328Pdef.inc"
    
    ldi r21,high(ramend)  
    out sph,r21        
    ldi r21,low(ramend)    
    out spl,r21        
  
    ldi r16,(1<<TXEN0)     ; enable transmit  
    sts ucsr0b, r16       
    ldi r16,(1<<UCSZ01)|(1<<UCSZ00)
    ;ldi r16,(1<<UCSZ01)|(1<<UCSZ00)|(1<<umsel0) ;no good
    sts ucsr0c, r16 ; usart control/status register
    ldi r16,0x66    ; the baud rate, 9600 on 16 megaherz chip
    sts ubrr0l,r16
    ldi r16,0x00    ; the baud rate, 9600
    sts UBRR0H,r16
  
  again:
    ldi r17,'y'    
    call trnsmt      
    ldi r17,'e'    
    call trnsmt      
    ldi r17,'s'    
    call trnsmt      
    ldi r17,' '    
    call trnsmt      
    rjmp again      
  
  trnsmt:
    ; sbis doesnt work because ucsr0a is not in standard
    ; i/o space so it cant be used with sbis - skip if bit in i/o is set. 
    ; sbis UCSR0A, UDRE0
    lds r16, UCSR0A       ; usart control, status register
    sbrs r16, UDRE0       ; is UDR empty?
    rjmp trnsmt           ; if not, then just wait 
    sts UDR0,r17          ; if empty tx next character
    ret
    
  \end{lstlisting}


\emph{ Transmit a string through the usart serial }
  \begin{lstlisting}
  .include "m328Pdef.inc"
    
  .cseg
  
   message: .db 5, "hello"      ; counted string message
    
    ldi r21,high(ramend)  
    out sph,r21        
    ldi r21,low(ramend)    
    out spl,r21        
  
    ldi r16,(1<<TXEN0)     ; enable transmit  
    sts UCSR0B, r16       
    ldi r16,(1<<UCSZ01)|(1<<UCSZ00)
    ;ldi r16,(1<<UCSZ01)|(1<<UCSZ00)|(1<<umsel0) ;no good
    sts UCSR0C, r16      
    ldi r16,0x66    ; the baud rate, 9600 on 16 megaherz chip
    sts UBRR0L,r16
    ldi r16,0x00    ; the baud rate, 9600
    sts UBRR0H,r16
  
    rcall transmitx

  here: rjmp here

  ; forth style header
  serial:
    .db 6, "serial"
  serialx:
    ret

  transmit: 
    .dw serial
    .db 8, "transmit"
  transmitx:
    ldi r17,'y'    
    call tx
    ldi r17,'e'    
    call tx      
    ldi r17,'s'    
    call tx      
    ldi r17,' '    
    call tx      
    ret

  tx:
    lds r16, UCSR0A       ; usart control, status register
    sbrs r16, UDRE0       ; is usart data register empty?
    rjmp tx               ; if not, then just wait 
    sts UDR0,r17          ; if empty tx next character
    ret
    
  \end{lstlisting}

\emph{ Transmit a string stored in program memory via usart serial  }
   ------
   .include ``m328Pdef.inc''
   .dseg
   .cseg
     ; start the serial usart in transmit mode
     ldi r16, 0 | 1$<$$<$txen0  ; enable transmit only
     sts UCSR0B, r16        ; put in usart control status reg 
     ldi r16, 0 | 1$<$$<$ucsz01 | 1$<$$<$ucsz00    ; 8 bit, 1 stop, no parity
     sts UCSR0C, r16               
     ldi r16, 0x66    ; the baud rate, 9600 on 16 megaherz chip
     sts UBRR0L, r16
     ldi r16, 0x00    ; the baud rate, 9600
     sts UBRR0H, r16
   
     ldi ZH, high(buffer$<$$<$1)   ; not sure why $<$$<$1 low byte of address
     ldi ZL, low(buffer$<$$<$1)
     lpm r16, Z+               ; 1st byte of string is the count 
   nextchar:
     lpm r20, Z+           ; get contents of byte at z into r16, increment

     tx:
       lds r17, UCSR0A     ; usart control, status register
       sbrs r17, UDRE0     ; is usart data register empty?
       rjmp tx             ; if not, then just wait 
       sts UDR0,r20        ; if empty tx next character

     dec r16               ; decrement counter
     brne nextchar         ; loop while counter $>$ 0

   here: 
     rjmp here           ; loop for ever

   buffer: 
     .db 9, ``hello itt''   ; a counted string in the buffer

   ,,,


\subsection{Receiving Rx}

  This is not working 13 april 2020 and I am not sure why.

\emph{ Receive some chars from usart into a buffer   }
  \begin{lstlisting}
  .include "m328Pdef.inc"
    
    .def counter = r20
  .dseg
    buff: 
      .byte 10
  .cseg
  .org 0 
    jmp start
  start:
    ; set up stack
    ldi r21,high(ramend)  
    out SPH,r21        
    ldi r21,low(ramend)    
    out SPL,r21        

    rcall serialx

    ldi r17,'o'    
    call transmit 
    ldi r17,'k'    
    call transmit 
    rcall newline 

  here:
    ; rcall accept
    ldi xl, low(buff)       ; make x a pointer to buffer in sram
    ldi xh, high(buff)      ; 
    ldi r17, 'x'
    st X+, r17 
    ldi r17, 'y'
    st X+, r17 
    ldi r17, 'z'
    st X+, r17 
    ldi r17, 0 
    st X+, r17 
    rcall print
  halt:
    rjmp halt 

  serialx:
    ldi r16, 0 | 1<<txen0 | 1<<rxen0      ; enable transmit receive 
    sts UCSR0B, r16       
    ldi r16, 0 | 1<<ucsz01 | 1<<ucsz00    ; parity etc
    sts UCSR0C, r16      
    ldi r16,0x66    ; the baud rate, 9600 on 16 megaherz chip
    sts UBRR0L, r16
    ldi r16,0x00    ; the baud rate, 9600
    sts UBRR0H, r16
    ret

  ; print a zero terminated string
  print:
    ldi xl, low(buff)       ; make x a pointer to buffer in sram
    ldi xh, high(buff)      ; 
  nextchar:
    ldi r17, ':' 
    rcall transmit
    ldi r17, '*' 
    rcall transmit
    ld r17, X+
    rcall transmit
    tst r17
    brne nextchar
    rcall newline
    ret

  ; first byte is count.
  accept:    
    ldi xl, low(buff)       ; make x a pointer to buffer in sram
    ldi xh, high(buff)      ; 
    ldi r20, 5                ; use r20 as a counter
    mov yl, xl                ; save pointer in y to write count
    mov yh, xh 
  nextch:
  wait:
    lds r16, UCSR0A    ; get usart status info
    sbrs r16, RXC0     ; has a byte been received?
    rjmp wait          ; if not just wait for one.

    lds r17, UDR0      ; get received byte
    st X+, r17         ; store in the buffer
    dec r20
    brne nextch        ; loop while r20 > 0
    rcall newline
    ret

  newline:
    ldi r17, 10 
    call transmit 
    ldi r17, 13 
    call transmit 
    ret
    
  transmit:
    lds r16, UCSR0A       ; usart control, status register, cant use sbis
    sbrs r16, UDRE0       ; is usart data register UDR empty?
    rjmp transmit         ; if not, then just wait 
    sts UDR0, r17         ; if empty tx next character
    ret
    
  \end{lstlisting}

\emph{ Receiving using the usart serial interface }
  \begin{lstlisting}
  .include "m328Pdef.inc"
    
  .dseg
  .cseg
  
  message: .db "hello",0

    ldi r21,high(ramend)  
    out sph,r21        
    ldi r21,low(ramend)    
    out spl,r21        
  
    ldi r16,(1<<txen0)|(1<<rxen0)     ; enable transmit receive 
    sts  UCSR0B, r16       
    ldi r16,(1<<UCSZ01)|(1<<UCSZ00)
    sts UCSR0C, r16      
    ldi r16,0x66    ; the baud rate, 9600 on 16 megaherz chip
    sts UBRR0L,r16
    ldi r16,0x00    ; the baud rate, 9600
    sts UBRR0H,r16
  
    ldi r17,'y'    
    call trnsmt      
    ldi r17,'e'    
    call trnsmt      
    ldi r17,'s'    
    call trnsmt      
    ldi r17,' '    
    call trnsmt      
  
  again:
    lds r16, UCSR0A    ; get usart status info
    sbrs r16, RXC0     ; has a byte been received?
    rjmp again
    lds r17, UDR0      ; get received byte
    inc r17            ; add one to the character
    sts UDR0, r17      ; just send it back
    rjmp again

  trnsmt:
    lds r16, UCSR0A       ; usart control, status register, cant use sbis
    sbrs r16, UDRE0       ; is usart data register UDR empty?
    rjmp trnsmt           ; if not, then just wait 
    sts UDR0,r17          ; if empty tx next character
    ret
    
  \end{lstlisting}

\section{Interrupts}

  Interrupts are a large and important topic in microcontrollers
  Assembly programming allows us to see clear what is going on 
  when an interrupt is triggered. 
   
  jargon: isr - interrupt service routine

  All interrupt vectors from Mazidi will need to be changed.

  Probably best to use the symbolic constant for interrupt 
  vectors (which will make code slightly more portable between
  avr micros).

  eg OC0Aaddr = timer/counter0 compare match vector 
     (instead of 0x001C on an atmega328p)

ISR INTERRUPT SERVICE ROUTINE ...

  There are 2 ways to write the ISR. Put a jump to a service
  routine at the interrupt vector, or (if you dont have other
  interrupts vectors to get in the way), write the ISR at
  the vector location (with no jump).

\emph{ Isr in-place with no jump  }
  \begin{lstlisting}
  .include "m328Pdef.inc"
  .org 0        
    jmp wakeup     ; on reset vector
  .org 0x02        ; external interrupt 0 vector 
    ; put isr code right here! But you wont be able 
    ; to use the interrupts with vectors at 0x04, 0x06 etc...
    reti
  wakeup:  
    ; code here.
  \end{lstlisting}

\emph{ Jump to isr }
  \begin{lstlisting}
  .include "m328Pdef.inc"
  .org 0        
    jmp wakeup          ; on reset vector
  .org 0x02      
    jmp  external0isr   ; external interrupt 0 vector 
  wakeup:  
  here: jmp here
  external0isr:
    ; service the interrupt.
    reti
  \end{lstlisting}

\subsection{Priority}
   
   The priority of an interrupt is reflected by its position in
   the interrupt vector table. The lower the vector the higher
   the priority.

\subsection{Context Saving}

  Interrupt may be the source of subtle errors since they are
  essentially a type of multitasking. Its probably a good 
  idea to save the sreg (flag register).

\emph{ Save sreg in an isr }
  \begin{lstlisting}
    .include "m328Pdef.inc"
    sampleIsr:
      ; push other registers to save here
      in r20, sreg
      push r20
      ; ...
      pop r20
      out sreg, r20
      ; pop other saved registers here
      reti
  \end{lstlisting}

\subsection{Vectors}

  Each type of interrupt has a fixed vector. So the jump to the interrupt
  service routine must be placed at that vector. It is much better to use the
  name for the vector rather than an actually address. eg

\begin{lstlisting}
  .org OC0Aaddr  ; yes!!
\end{lstlisting}
\begin{lstlisting}
  .org 0x03      ; no!!
\end{lstlisting}

  These names are in the file m328Pdef.inc or a corresponding file for other
  AVR micro-controllers.

\emph{ Example vector code  }
  \begin{lstlisting}
  .nolist
  .include "m328Pdef.inc"
  .list
  .cseg
  .org 0        
    rjmp onreset 
  .org OC0Aaddr    ; timer0 compare match interrupt vector
    jmp timerMatch 
    ; or use rjmp if with 2K of vector
  onreset:
    ; ... main code
  here:
    rjmp here 

  ; interrupt service routine for timer0 match 
  timerMatch:
    reti

  ,,,,

PIN CHANGE INTERRUPTS ....

  Triggered on rising and falling edges.
  These can be configured for a number of pins.

TIMER INTERRUPTS ....

 
EXTERNAL OR HARDWARE INTERRUPTS ....

  The external interrupt int0 appears mapped to pin 2 (portD,2) on
  arduino uno/nano/duemilenove, and int1 to pin 3 (portD,3)

  The code below works in conjunction with a switch connected 
  from portd,2 to ground, and an led on portc.3. The led should
  toggle once when the button is pressed

  GICR in some avr chips is EICRA in the atmega328

  Connect a button (normally open) to portd.2 (int0) of the 
  arduino, from ground, and connect a LED on portc.3

  * trigger an interrupt when pin goes low (eg button push)
  \begin{lstlisting}
  .include "m328Pdef.inc"
  .org 0        
    jmp main           ; on reset vector
  .org 0x02      
    jmp external0isr   ; external interrupt 0 vector 
  main:
    ; initialize stack (because interrupts use it)
    ; but since 2006, avr chips do this automatically
    ldi r20, high(ramend)
    out SPH, r20
    ldi r20, low(ramend)
    out SPL, r20        ; 

    sbi DDRC, 3       ; portC.3 is output
    sbi PORTD, 2      ; pull-up activated 
    ldi r20, 1<<INT0  ; enable int0
    sts EICRA, r20    ; interrupt control register
    sei               ; enable all interrupts
    here:
      ; micro can do other work here
      rjmp here

  external0isr:
    in r21, PINC    ; pinc seems to be output values on PORTC 
    ldi r22, 0x08
    eor r21, r22    ; toggle with exclusive OR
    out PORTC, r21  ; write to portc
    reti

  \end{lstlisting}

  working, tested on arduino ``uno''

\emph{ Trigger an interrupt on falling edge of pin (eg button push) }
  \begin{lstlisting}
  .include "m328Pdef.inc"
  .org 0        
    jmp main           ; on reset vector
  .org 0x02      
    jmp external0isr   ; external interrupt 0 vector 
  main:  
    ldi r20, high(ramend)
    out SPH, r20
    ldi r20, low(ramend)
    out SPL, r20        ; init stack 
    ldi r20, 0x2        ; int0 falling edge triggered
    sts EICRA, r20      ; external interrupt control register

    ;sbi ddrc, 3        ; portc.3 = output 
    sbi DDRB, 5         ; portb.5 = output (led on arduino pin 13)
    sbi PORTB, 5        ; turn on led
    sbi PORTD, 2        ; activate pull-up (PD3 is int1)
    ldi r20, 1<<int0    ; enable external interrupt 0
    out EIMSK, r20      ; external interrupt mask register
    sei                 ; globally enable interrupts
  here:  jmp  here    
  external0isr:
    in r21, PORTB
    ldi r22, 1<<5      ; portb5, toggle    
    eor r21, r22
    out PORTB, r21    
    reti
 \end{lstlisting}

\section{Analogue To Digital Conversion}

  http://maxembedded.com/2011/06/the-adc-of-the-avr/
    A reasonable explanation of the functioning of the 
    adc for avr chips.

  ``Adc'' is yet another acronym meaning analogue to digital 
  conversion and is included in almost all microcontrollers.
  Most sensors work by varying resistance or voltage depending 
  on some environmental factor such as light, sound, temperature,
  pressure etc. This varying resistance gets translated into a 
  varying voltage input into one of the avr chips input pins.
  The varying voltage is refered to as an 'analogue signal' or 
  analogue input.
  
  The ADC module of the microcontroller converts this into a 
  digital number within a certain range. So that the MC can
  then analyse the value of the input.

  
\emph{ Read the adc }
  \begin{lstlisting}
     .def temp = r16
   adcRead: 
     lds temp, ADCSRA    ; a/d control status register 
     ori temp, (1<<ADSC) ;  
     sts ADCSRA, temp    ; Write

   loopx:
     lds temp, ADCSRA    ; 
     sbrc temp, ADSC
     rjmp loopx     
     lds r17, ADCL     ; low byte
     lds r18, ADCH     ; high byte (only 2 bits, because a/d is 10bit)
     ret

  This is mazidi example 13.3 Untested code (july 2018) with any arduino board.
  
  * reads temperature sensor and displays on port D 
  \begin{lstlisting}
  ; Needed to fix the code below for the atmega328 because the 
  ; ADCSRA (a/d conversion status register) is memory mapped 
  ; and cant use sbi, sbis etc

   .include "m328Pdef.inc"

     ldi r16, 0xFF
     out DDRD, r16   ; make all portD output
     ldi r16, 0
     out DDRB, r16   ; make portA input for A/D
     ldi r16, 0x87   ; enable ADC and select ck/128
     sts ADCSRA, r16
     ldi r16, 0xE0   ; 2.56V vref ADC0 single ended
     sts ADMUX, r16  ; left justified data
   readadc:
     clr r16
     ldi r16, 1<<ADSC ; start the convertion
     ldi r17, 0x87
     or r16, r17      ; keep adc enabled and ck/128 
     sts ADCSRA, r16  ; do it 
   wait:
     lds r16, ADCSRA
     sbrs r16, ADIF     ; is conversion completed
     rjmp wait          ; just wait
     ldi r16, 1<<ADIF   ; 
     ; sbi ADCSRA, ADIF   ; write 1 to clear ADIF flag
     lds r17, ADCSRA
     or r16, r17 
     sts ADCSRA, r16
     lds r16, ADCH       ; read only highbyte for 8 msb of result
     out portd, r16
     rjmp readadc       ; continue

  \end{lstlisting}

\section{Pulse Width Modulation Or Pwm}

  
  This stands for pulse width modulation. PWM has 2 main characteristics,
  the frequency of the wave (eg 50 herz, 100 Khz, etc) and the 
  pulse width, which is the amount of time the signal remains high.
  The duty cycle is the pulse width measured as a percentage of the 
  period of the wave.

  Note in timer0 and timer2 fast pwm mode, it is not possible to
  vary both frequency and duty cycle/pulse width at the same time.
  If you want to vary the pulse width, then the timers will always
  count up to 256.

  This is a kind of approximated analogue output using 
  digital highs and lows. Pulse width modulation can be used to 
  control motors that vary their speed or position (eg servo motors)
  depending on the power supplied. 

  Pwm is achieved with the 3 timer/counters. timer0 and timer2 
  are 8 bit counters and timer1 is a 16 bit counter.

  Phase correct or normal PWM counts up until the OCRnA value
  is reached and toggles the signal, then it counts down again
  and toggles the signal again when it reaches the OCRnA value.
  ``fast'' PWM only counts upwards and therefor run at twice 
  the speed of normal PWM.

  Stepper and DC motors should use normal PWM and servo motors
  can use fast PWM.

  Pwm is also a way to modify the output voltage of a pin, and
  so is a kind of ``analog'' output. We can see PWM as the 
  output version of ADC input.
  
  For pwm it is not possible to change the output pin for a given
  timer/counter (but there are 2 output pins for each timer)

\emph{ Timer output pins for atmega328 and arduino }
  ------
    Timer output Arduino output	Chip pin	Pin name
    OC0A         6	        12	PD6
    OC0B         5        	11	PD5
    OC1A         9	        15	PB1
    OC1B         10       	16	PB2
    OC2A         11	        17	PB3
    OC2B	 3	        5	PD3
  ,,,,

\emph{ Atmega normal (not ``fast'') pwm frequency formula: }
  ----
  freq = clock / (2 * N * TOP) 
  where 
    N=prescalar(1,8,64,256,1024)
    clock = system clock (eg 16Mhz on atmega328)  
    TOP is the value to be loaded into ICR1
    To get 50 Herz frequency:
    Prescaler N = 1 then TOP(ICR1) = 160000 (too big!)
    Prescaler N = 8 then TOP(ICR1) = 20000 
    Prescaler N = 64 then TOP(ICR1) = 2500 
    Prescaler N = 256 then TOP(ICR1) = 625 
    Prescaler N = 1024 then TOP(ICR1) = 156.25 (no good, cant use decimals)

  50 herz = 16000000/(2*8*top)
  so top = 16000000/(2*8*50) = 20000 

  I would suggest prescaler 8 and set ICR1 to 20000 
  because this will allow you to change OCR1A between 
  1000 and 2000 to obtain 1 - 2 ms high pulses.

  To change the position of the servo, you would change OCR1A between 1000 and
  2000 for a prescalar of 8 

  So it is better to use the smallest prescalar that will do the job, for
  accuracy.

  ,,,

\subsection{Pwm For Servo And Brushless Motors}

  Each timer can drive 2 outputs in pwm mode (using OCRnA and OCRnB).
  The output pins for each timer are fixed and cannot be changed.
  Each timer can drive 2 servos with different pulse widths (duty
  cycles) but at the same frequency.

  So the atmega328 MCU can drive 6 servo motors without resorting
  to software techniques (``bit banging'')

  It is also possible to use timer0 and timer2 (both 8 bit timers) for
  driving servos and brushless motors. For a 16Mhz atmega328, the
  minimum frequency that can be achieved using Fast PWM and a prescalar
  of 1024 (the maximum) is 61 herz. Although this is faster than the
  recommended 50hz for servo motors, it should work.

  At 61 herz, period is 64 uS (microseconds) and 16 gives
  a 1\% duty cycle and 31 gives a 2\% duty cycle which is the 
  normal range for driving a servo.

  An alternative is to use normal or phase correct pwm, which 
  counts up, and then down again, which can achieve a minimum
  frequency of about 30herz.

\emph{ Formula for normal pwm and ctc (clear timer on compare) modes }
\begin{lstlisting}
  freq = clock / (2*N*top)    where N is prescalar
\end{lstlisting}

\emph{ Formula for fast pwm mode  }
\begin{lstlisting}
  freq = clock / (N*top)  
\end{lstlisting}

\subsection{Pwm For Servos On Timer Zero}

  In fast pwm mode 3 for timer0 and timer2, it is not possible to
  vary both frequency and pulse width, just pulse width.
   the timer counts up to 255 every time.,
  
  In fast pwm mode 7 (timer0/2) only the frequency can be modified
  not the pulse width (which is not useful for driving servo
  motors or dimming leds.)

\emph{ The meaning of the bit names }
  -----
    WGMnx ``waveform generation mode'' bits select timer mode 
      (eg fast pwm, ctc)
      n = timer number (0,1,2)
      x = bit number   (0,1,2...)
    COM ``compare match output'' bits select/invert output pin
    CSnx  ``clock select'' selects the prescalar and starts the timer.
      n = timer number (0,1,2)
      x = bit number   (0,1,2...)
  ,,,

\emph{ Dim an led with 50Mhz fast pwm wave on timer0 }
  -------
   .nolist
   .include ``m328Pdef.inc''  
   .list
   .def temp = r16        ; general purpose accumulator
   .dseg
   .cseg
     rjmp start
   start: 
     ; assume stack pointer is automatically initialised.

     ; output pins for timer0 are PD6/PD5 or arduino 6/5
     sbi DDRD, 6     ; portD,6 as output, timer0 1st output pin

     ; prescalar determines wave frequency/period
     ; in mode 3 timer0 and timer2 always count upto 255.
     ; formula: freq = Fosc / (N*256)  
     ;   N is prescalar 
     ;   ``freq'' is the wave frequency required 
     ;   ``Fosc'' is the system clock (16Mhz on atmega328 for arduino)
     ;  50 herz = 16000000/(1024*256)
     ;  so, freq  = 16000000/(1024*256) = approx 61hz
     ;  gives a 61hz frequency (16Mhz Fosc, prescale 1024). 
     ;  This should be sufficient for driving a servo motor.
     ;  Then the value in OCR0 is the pulse width
     ;     

     ; use ``out'' not ``sts'' on the atmega328
     ; COM0A1 enable only the 1st output pin PD6
     ; wgm bits for Fast PWM, mode 3 
     ldi temp, 1$<$$<$WGM01 | 1$<$$<$WGM00 | 1$<$$<$COM0A1 
     out TCCR0A, temp
     ; starts timer with prescalar = 1024
     ; loading clock (``CS'' bits) starts the timer)
     ldi temp, 1$<$$<$CS02 | 1$<$$<$CS00
     out TCCR0B, temp

     ; OCR0A which determines pulse width of pwm wave
     ; OCR0A should be between 0 and 255 for changing the 
     ; brightness of the led 
     ldi temp, 200       ; make led bright (about 80\%)
     out OCR0A, temp     ; load compare value high byte 

   main:
     ; sleep for eg 5ms and vary the OCR0A value here for 
     ; dimming and brightening the led 
     rjmp main
    
  ,,,,

\subsection{Pwm For Servos On Timer One}

\emph{ Fast pwm in assembly on timer1, suitable for servo motor }
  ----
  ;  I use mode 14, FAST PWM, timer1.
  ;  The period of pulses is set with ICR1.
  ; The width of pulses is set with OCR1A (OCR1B for the second servo).
  ;  DDRD = BitVal(5); //PORTD5 pin as output
  ;  PORTA = 0x0F; //Enable pullups
  ;  ICR1 = 0x4800; //Set limit Timer, $\sim$20ms period on 7.3728MHz
  ;  TCCR1A = BitVal(WGM11) | BitVal(COM1A1); //Fast PWM, Wave Form output
  ;completes bits needed for Fast PWM and starts timer no pre-scaler. 
  ;  TCCR1B = BitVal(WGM13) | BitVal(WGM12) | BitVal(CSS10);
  ;  OCR1A = 0x0566; //1.5mS $\sim$0x0566 - 1.0mS $\sim$0x039A - 2mS $\sim$0x0732

  ; we can translate this in a straight forward way to asm
  ; see the code below for an avr asm translation
  ,,,


\emph{ 50 mega herz fast (non inverted?) pwm wave on timer1 }
  -------
   .nolist
   ;atmega328 definitions (for arduino ``uno'' etc)
   .include ``m328Pdef.inc''  
   .list
   .def temp = r16          ;general purpose accumulator
   .dseg
   .cseg

     ; output pins are fixed for atmega pwm
     ; output pins for timer1 are PB1/PB2 or arduino 9/10
     sbi DDRB, 1     ; portB,1 as output
     ldi r16, 0x0F   ; enable pullup resistors, but why?
     ;mov PORTB, temp

     ; fast pwm wav frequency, $\sim$20ms period on 16Hhz with prescalar 8
     ; ICR1 = 40000
     ; we need to load the 16 bit value as two 8 bit values
     ; into ICR1H and ICR1L

     ; load ICR1 which determines frequency/period
     ; use the formula
     ;    freq = clock / (N*top)  
     ;      where N is prescalar and top is compare match value. This is 
     ;      freq is the wave frequency required and clock is the system 
     ;      clock (16Mhz on atmega328 for arduino)
     ;      a 16 bit value for timer1 in the ICR1H/ICR1L registers
     ;  50 herz = 16000000/(8*top)
     ;  so, top = 16000000/(8*50) = 40000 -$>$ ICR1H
     ;  Then the value in OCR1H/OCR1L is a percentage of 20000
     ;     
     ldi temp, high(40000) ;  need a 50hz frequency with 16 Mhz
                            ;
     sts ICR1H, temp        ; 
     ldi temp, low(40000)
     sts ICR1L, temp        ; 

     ; COM1A1 only one output
     ldi temp, 1$<$$<$WGM11 | 1$<$$<$COM1A1       ; Fast PWM, wave form output
     sts TCCR1A, temp

     ; wgm bits for Fast PWM and starts timer with prescalar = 8
     ; loading clock starts the timer
     ldi temp, 1$<$$<$WGM13 | 1$<$$<$WGM12 | 1$<$$<$CS11   
     sts TCCR1B, temp

     ; for servo motors the value should be between 5\% and 10\% of ICR1 value 
     ; for dimming leds, the value should be between 0\% and 100\% of ICR1 value
     ; load OCR1A which determines pulse width of pwm wave
     ldi temp, high(3000)    ; need a 1-2 ms pulse width 
     sts OCR1AH, temp        ; load compare value high byte 
     ldi temp, low(3000)
     sts OCR1AL, temp        ; load compare value low byte 

   ; 50 Herz wave with variable pulse width
   main:
     ; sleep for eg 5ms and vary the ocr1a value here for 
     ; dimming and led or servo..
     rjmp main
    
  ,,,,

  An example in c to set up a pulse width modulated wave on pin 3 using
  an automatic toggle (no ISR is required, because the output pin toggle
  is part of the configuration).

\emph{ 50 herz pwm wave with .512ms pulse width on pin 3 (uno board) }
  ------
   pinMode(3, OUTPUT);
   pinMode(11, OUTPUT);
   TCCR2A = \_BV(COM2A0) | \_BV(COM2B1) | \_BV(WGM20);
   TCCR2B = \_BV(WGM22) | \_BV(CS22)| \_BV(CS21)| \_BV(CS20);           //
   OCR2A = 156;
   OCR2B = 4;
   // ocr2b = 20 is 2.56ms pulse width
   // ocr2b = 10 is 1.28ms pulse width
   // ocr2b = 11 is 1.42ms pulse width
   // these values are important for driving servos and brushless motor 
   // using an ESC, because the 180 degree servo arm rotates between 
   // about 1ms and 2ms pulse width at 50herz
  ,,,

\subsection{Bit Banging Pwm}

  The phrase 'bit banging pwm' refers to creating a pulse width
  modulation 'manually', by writing a high signal for a specified
  amount of time and then writing a low signal to the same pin
  for the remaining time of the duty cycle. 

  There is more coding required to achieve this, compared to 
  using the PWM mode of one of the timers, but it is useful
  when attempting to drive multiple servo motors, dimming leds,
  brushless motors, etc. Also, it is useful for learning about
  how pulse width modulation works.

  It is also handy when all of the uC timers are occupied doing
  something else.

  There are various options for 'bit banging' including using
  a timer or timers to generate the delays, or using a delay
  loop (which prevents the micro-controller from doing anything 
  else).

  One technique for software PWM is to assign ``time windows'' to each
  servo, which are staggered over the length of the wave period.
  So, if the frequency of the wave is 50hz, then the period of the
  wave is 20ms. We can assign a 1ms time window for each servo.
  In that window, we switch on the pulse for the next servo at the 
  beginning of the window and switch off the pulse for the previous
  servo, at some point in the window, to provide the correct pulse 
  width.

  This technique allows for driving 20 servos from one timer.


\emph{ Bit banging in arduino c }
  -------
    void setup() $\{$
      pinMode(13, OUTPUT);
    $\}$

    void loop() $\{$
      digitalWrite(13, HIGH);
      delayMicroseconds(100); // Approximately 10\% duty cycle @ 1KHz
      digitalWrite(13, LOW);
      delayMicroseconds(1000 - 100);
    $\}$
  ,,,,

\emph{ Bit bang pwm example }
  \begin{lstlisting}
   .include "m328Pdef.inc"  ;atmega328 definitions
   .def temp = r16          ;general purpose accumulator
   .dseg
   .cseg

   ; 50 Herz wave with variable pulse width
   main:
     rjmp main
  \end{lstlisting}

\subsection{Phase Correct Pwm}
 
  The timer counts up, toggles off the output when compare/match value
  is reached, continues counting to 0xFF, then starts to count down,
  then toggles again the output when compare/match value is reached
  on the down-count. This create a symetrical wave with the phase
  always aligned.

\subsection{Fast Pwm}

  The timer/counter only counts up (as with other timer modes). In
  phase correct timer counts up and down. The timer counts up and toggles
  the output when it reaches the compare/match value. Then it *keeps* 
  counting until it reaches overflow 0xFF or 0xFFFF. This is how 
  the ``duty cycle'' (time high/ time low) is varied, by varying the 
  value in the compare/match value. Using this technique we can create
  a sound signal. 

  The pwm mode is different from the ctc mode because in ``ctc'' mode,
  when the compare/match value is reached, the timer is reset to zero,
  and then continues to count up.

  A table of sound samples (usually 8kHz 8 bits) is read and the 
  duty cycle is varied in the overflow interrupt with the timer in
  PWM mode.
  
  This is very similar to the ctc (clear-timer-on-compare) mode

   The code below needs to be modified because it is unreadable,
   since it uses bitmaps instead of bit-names for configuration.

\emph{ Attiny13/atmega328 pwm mode (toggle) timer0 }
   \begin{lstlisting}

   ; code seems incomplete, where is pulse width

   ;.include "tn13def.inc"   ;(attiny13 definitions)
   .nolist
   .include "m328Pdef.inc"  ;atmega328 definitions
     .def temp = r16           ;general purpose accumulator
   .dseg
   .cseg
   .org 0x00
     sbi DDRB, 0          ;set oca0/portb.0 for output
     ldi A, 0b01000011    ;set to ctc mode
     out TCCR0A, temp 
     ldi A, 0b00001101    ;set prescaler/divider to /1024        
     out TCCR0B, temp        
     ldi A, 128           ;set the compare register
     out OCR0A, temp      ;to 128
     here: 
       ; the micro can do something else here
       rjmp here 
   \end{lstlisting}


\subsection{Interrupts In Pwm Mode}

  Interrupts are also available in pwm mode, which is interesting. This
  means we can do pwm to any pin on the arduino

  In the TIMSK0 register there are bits for 
   OCIE0A, OCIE0B, and TOIE0
   so we can generate an interrupt on compare match and also overflow
   meaning that we can do pwm to any pin.

  This means we can experiment with dimming the led at pin13

\emph{ An example in c }
  ------
     // enable the timer/counter match interrupt
     TIMSK2 |= (1$<$$<$OCIE2B); // Output compare B match
     // clear interrupt flag
     TIFR2 |= (1$<$$<$OCF2B);
     // enable global interrupts enabled in main startup code
     // sei();
  ,,,,

PULSE WIDTH MODULATION IN C ...

\emph{ Pwm code for an atmega8  }
  \begin{lstlisting}

  #define fillrate OCR2A 

  // main()

  PORTB=0x00;
  DDRB=0x08;  //We use PORTB.3 as output, for OC2A, see the atmega8 reference manual

  // Mode: Phase correct PWM top=0xFF
  // OC2A output: Non-Inverted PWM
  TCCR2A=0x81;
  // Set the speed here, it will depend on your clock rate.
  TCCR2B=0x02;
  // for example, this will alternate between 75% and 42% PWM
  while(1)
  {
      fillrate = 191; // ca. 75% PWM
        delay_ms(2000);

      fillrate = 107; // ca. 42% PWM
        delay_ms(2000);
   }
   \end{lstlisting}


\section{Square Waves}

 A square wave is a wave with a 50\% duty cycle, meaning that it spends equal
 time high and low. This can be achieve with an automatic ``toggle'' on a 
 certain pin, so that no ISR interrupt service routine is necessary. However
 this means that a particular pin, must be used for output.
  
 We could use this square wave to drive a piezo speaker, for example and 
 produce a tone. We can then do other things with the micro in the main loop.

\emph{ Set up 38Khz square wave with timer 1 on uno, ctc on compare match, oc1a pin toggle }
 --------
 // timer1 initialization
  noInterrupts(); // disable all interrupts
  TCCR1A = 0;
  TCCR1A |= (1 $<$$<$ COM1A0);     // setup OC1A pin in toggle mode
  TCCR1B = 0;
  TCCR1B |= (1 $<$$<$ WGM12);   // clear timer/counter 1 on compare match
  TCCR1B |= (1 $<$$<$ CS10);    // no prescaler (timer clock = system clock)
  TCNT1 = 0;                // reset counter
  OCR1A = 210;              // set value on TCNT1 for given IR frequency (AVRCLOCK/IRFREQUENCY/2)
  // no dont enable interrupts here!
  // TIMSK1 |= (1 $<$$<$ OCIE1A);             // enable timer compare interrupt
  TIFR1 = (1$<$$<$OCF1B);
  interrupts();                        // enable all interrupts

  // main loop
  // ....
 ,,,

\section{Time}

  The arduino C millis() function returns a long unsigned integer.
  This can deal with time periods up to approximately 50 days.

\section{Wave Forms}
  
  ``wave'' is a combination of signal on and signal off. We normally
     think of a wave as curvy, but digital waves arent.
  ``Duty Cycle'' is time-high/time-low (as a percentage)
  ``Period'' is the time for one complete wave.
  ``Frequency'' number of waves per second (Herz)
  ``square wave'' wave (on/off) with duty cycle 50\%. That is 
     equal time on and off.

  Mazidi page 518 (input capture and wave generation in avr) has
  an example of wave generation using a wave table. This appears
  to be a digital wave (0/1) which could imitate a sine wave by
  on/off time variation.
  
  The technique below could make a sine wave for music generation
  (or led dimming?)

   But this should be pwm, no?

\emph{ Wave generation using timer0 compare/match toggle and interrupt  }
   ---------
    ; untested 2020 

    .include ``m328Pdef.inc''
      .def counter = r29
      .def temp = r18

    .org 0x0
       rjmp main 
    .org OC0Aaddr     ; timer/counter0 compare match A vector 
       rjmp timerMatch
     main:
       ; auto initialize stack
       sbi DDRB, 5    ; pb5 as output
     begin:
       ; Set the Timer0 Mode to CTC clear timer on compare mode
       ldi temp, 1$<$$<$WGM01
       out TCCR0A, temp

       ldi temp, 69
       out OCR0A, temp ; initial compare/match value = 69

       ; set prescaler to 64 and start the timer
       ldi temp, 1$<$$<$CS01 | 1$<$$<$CS00
       out TCCR0B, temp

       ldi temp, 1$<$$<$OCIE0A
       sts TIMSK0, temp ; enable compare/match interrupt
       sei              ; global enable interupts
     here: 
       ; the micro can do other work here
       rjmp here

     ; timer0 match ISR
     timerMatch:
       ;sbi PORTB, 5 
       sbic pinb, 5    ;
       cbi portb, 5    ;
       sbis pinb, 5    ;
       sbi portb, 5    ;

       dec counter    ; 
       brpl next      ; if counter $<$ 0 reset table pointer Z to table(0)
       ldi zh, high(wavetable*2) 
       ldi zl, low(wavetable*2)
       ldi counter, 4 ; length of table
     next:
       lpm r28, Z+     ; load program memory (wave table)
       out OCR0A, r28  ; update compare/match value for timer0 
       reti            ; return from ISR

     ; the wave table has alternating high/low values for the wave
     ; period=value+1  eg 25 high, 50 low, 40 high
     wavetable: 
       .db 24, 49, 39, 34

   ,,,

  
\section{Timers And Counters}

  https://sites.google.com/site/qeewiki/books/avr-guide/timers-on-the-atmega328
     The best site. Examples in C, with tables and explanations.
     And prescaler lists.

  https://gist.github.com/Wollw/2381139
    atmega328 timer examples in C.

 https://www.avrfreaks.net/forum/tut-c-newbies-guide-avr-timers?page=all
   a good guide in C. with ctc in interrupt mode. Looks like code
   for atmega328p

  Timer/Counters are used to generate delays (from microseconds up
  to several seconds) for doing things like blinking lights or 
  driving piezo speakers. They are also used for generating square wave
  forms (with a given frequency and duty cycle). These wave forms can
  be used to drive speakers or motors. When used with an ISR 
  (interrupt service routine), they can be used to ``multitask'' in
  the microcontroller. That is, the microcontroller can perform
  several tasks at once, such as driving a speaker and transfering
  data.

  Timers, when they use an external clock are referred to as ``counters''.
  In normal mode we load the timer/counter with an initial value
  and wait until it ``overflows'' (reaches 255 or 2\^{}16). We can check
  this overflow using the TOVn (Timer overflow flag).

  In CTC mode (Compare match mode) we load a match value and the 
  timer/counter counts up from zero until the match value is reached.
  We wait for this by watching a different flag. (Or set an interrupt
  to fire when the value is matched). On the face of it, there is 
  not much practical difference between the 2 modes. 

  However, CTC mode is slightly simpler because we do not need to
  reload the counter with its start value after each overflow. And
  if an interrupt is used, we do not have to reset the compare/match flag
  after each match.

  page 346 mazidi, use timer1 to toggle led once per second
  Example 9.33

  http://electronics.stackexchange.com/questions/2057/polyphonic-sounds-from-a-microcontroller
    some timer info

   timer (or counter) in normal mode, counts 0 to 255 then sets overflow.

\subsection{Frequencies And Periods}

  frequency is in herz, periods in seconds or milliseconds.

\emph{ Some frequencies in the world }
  ----
    human pulse - 1-2hz
    a440 musical note - 440hz
    Amethyst wood-star hummingbird wing rate - 80hz
    Giant hummingbird wing rate - 10 - 15hz
  ,,,

\subsection{Jargon Acronyms And Terminology}

  There is a lot of this

\emph{ Terminology }
  -----
    duty cycle - percentage of time high/time low for wav
    period - time taken for one wave (seconds)
    frequency - number of waves per second (herz)
  ,,,,

  ctc - ``clear timer on compare'' mode
  pwm - ``pulse width modulation'' mode

\emph{ The meaning of the bit names }
  -----
    WGMnx ``waveform generation mode'' bits select timer mode 
      (eg fast pwm, ctc)
      n = timer number (0,1,2)
      x = bit number   (0,1,2...)
    COM ``compare match output'' bits select/invert output pin
    CSnx  ``clock select'' selects the prescalar and starts the timer.
      n = timer number (0,1,2)
      x = bit number   (0,1,2...)
  ,,,
  
\subsection{Stopping Timers}

  Load 0 into the clock select bits to stop any of the timers

\subsection{Timer Modes}

  This is a quick summary of the different timer/counter modes
  All these modes can be used with an interrupt on overflow/compare-match
  or by polling flags.

  Timer0 and Timer2 are 8bit, Timer1 is 16bit

   normal: 
     load counter with something (or 0). start counter. counter
     counts up to overflow (0xFF for 8 bit timers, 0xFFFF for 16 bit)
     Overflow triggers overflow flag in TIFR0/1/2 or triggers 
     interrupt. Either poll the overflow flag, or write an interrupt
     service routine to do something.

   ctc: ``clear timer on compare''. 
     Put the ``compare'' value in OCR$<$n$>$ (eg OCR0). The timer/counter
     counts up to the compare value, then automatically resets to 0.
     Poll compare flag or write interrupt.

   pwm fast: "pulse width modulation, fast mode"
     put value in OCR0, OCR1, or OCR2. Start timer. 
     The timer/counter counts up to the compare 
     value, and toggles output pin automatically. Timer continues
     counting up until overflow. Resets to zero. 
     Poll overflow flag or write ISR (``interrupt service routine'').
     Modify the OCR$<$n$>$ compare value to change duty cycle of square wave 
     (time high versus time low). eg Can be used to emit sound samples 
     or drive dc/servo motor

   pwm phase correct: "pulse width modulation, phase correct mode"
     Put a value in OCR$<$n$>$ Start the timer. Timer counts up to compare 
     value, and toggles output pin automatically. Timer continues
     counting up until overflow. Timer starts to count *down*.
     Poll overflow flag or write ISR
     Modify OCR compare value to change duty cycle of square wave 
     (time high versus time low). produces a symmetrical square wave


\subsection{Gotchas}
  
   Address arithmetic in avr assembler is tricky because the 
   compiler puts in extra zero to pad out odd numbered addresses.

   Big gotcha!! timer1 has memory mapped control registers, so
   you have to use STS to load data into them, but timer0 is
   does not, so use OUT!! Using STS with timer0 results in timer0
   mysteriously doing nothing but using OUT with timer1 results 
   in a compile error.

   The atmega32 (not 328) only has one control register TCCR0
   but the atmega328 has 2. TCCR0A and TCCR0B. So the bits for 
   selecting the different modes (normal, ctc, pwm) are different.
   This means that Mazidi code (written for atmega32) will not 
   work without modification. 

   Interrupt vector locations are different for different avrs.
   Need to use symbolic constant names for interrupt vectors and 
   not numbers.

\emph{ Error, need to shift all bit names }
\begin{lstlisting}
  ldi r16, 0 | WGM01     ; error!
\end{lstlisting}
\begin{lstlisting}
  ldi r16, 0 | 1<<WGM01  ; correct!
\end{lstlisting}

   This is a gotchas because the compiler will not find the 
   error.

\emph{ Load the high byte of a 16 bit register first, }
     then the low byte. Read in the opposite order?

\subsection{Toggle Mode}

   The simplest way to drive a piezo or blinking led is to use 
   the output toggle with timer/counter 0,1,or2 in CTC (compare/match) mode.
   This reduces the code to 4 or 5 lines with no ISR because as soon
   as the timer/counter reaches compare/match value it clears the 
   flag and toggles a certain bit. 

   There are different toggle modes: 
      toggle on match, set on match, and clear on match.

   The frequency of the wave generated below should be 39.800 kHz
   on a 16 MHz atmega328p.

   Frequency Calculation for code below:
      200+1 clocks between timer matches (counts 0-$>$200)
      Time(wave) = 2*201 (time-low + time-high) = 402 clocks
      Freq = waves/second
      Freq = 16000000/402 = 39800 Hz

    this is not working yet on arduino uno

\emph{ Generate a square wave on timer0 with a ctc mode toggle }
   ---------
    .include ``m328Pdef.inc''
    .def temp = r20
    .cseg
      sbi ddrd, 3     ; 
      ;sbi PORTD, 3
      ldi r22, 200 
      out OCR0A, r22  ; set the match value
      ; in c TCCR0A = 1$<$$<$COM0A0 | 1$<$$<$WGM01;
      ldi r20, 1$<$$<$WGM01  ; 
      out TCCR0B, r20 ; load Timer control reg 
      ldi r20, 1$<$$<$CS00
      out TCCR0B, r20 ; load Timer control reg and start counting/toggling
      ; TCCR0B = 1$<$$<$CS00;
    here:
      ; We can do other work with the micro here, while timer2 is
      ; busy toggling pin pd7
      rjmp here
   ,,,

   Note: Timer2 prescalar values are different to Timer0 prescalar
   values (although both are 8 bit).

\emph{ Generate a square wave on timer2 with normal mode toggle }
   ---------
     ; Not working...
    .include ``m328Pdef.inc''
      sbi ddrd, 7   ; OC2 (PD7) as output
      ldi r22, 100
      out OCR2, r22 ; set the match value
      ldi r22, 0x11 ; com21:20=toggle, mode=normal, no prescale
      out TCCR2, r22; load Timer control reg and start counting/toggling
    here:
      ; We can do other work with the micro here, while timer2 is
      ; busy toggling pin pd7
      rjmp here
   ,,,

   Below is retrodan code, but this retrodan code doesnt seem to 
   work on atmega328. Uses magic numbers. NO good

\emph{ Attiny13/atmega328 ctc automatic wave-form mode (toggle) timer0 }
   \begin{lstlisting}

   ;.include "tn13def.inc"   ;(attiny13 definitions)
   .include "m328Pdef.inc"  ;atmega328 definitions
   .def A = r16             ;general purpose accumulator

   .org 0x00
     sbi DDRB, 0          ;set oca0/portb.0 for output
     ldi A, 0b01000010    ;set to ctc mode
     out TCCR0A, A
     ldi A, 0b00000101    ;set prescaler/divider to /1024        
     out TCCR0B, A        
     ldi A, 128           ;set the compare register
     out OCR0A, A         ;to 128
     ; also need to load the clock last I think
     here: 
       ; the micro can do something else here
       rjmp here 
   \end{lstlisting}


\subsection{Prescaler For Timers}

  Prescaler, or divider, divides the system clock by a given value.
  Prescaler values are limited to the following. The higher the 
  prescaler value, then the slower the timer with count up to 256
  
  The prescaler values are selected with the CSn$\{$0,1,2$\}$ bits
  in the "B" control register for the 3 atmega328 timers. Timerkj

  The prescaler value is set in the ``Timer/Counter Control Register''
  (TCCR0B in the atmega328 used in the many arduinos)


  \arrayrulecolor{gray}
  \begin{center}
  \begin{tabular}{ |rl| }
    \multicolumn{2}{c}{\textbf{ prescalar values for timer0/1 (n below is 0 or 1)  }} \\
  \hline

     \texttt{ 1 } & TCCRnB = 0b0000001     (1$<$$<$CSn0) eg: ldi temp, 1$<$$<$CS00 \\ 

     \texttt{ 8 } & TCCRnB = 0b0000010     (1$<$$<$CSn1) \\ 

     \texttt{ 64 } & TCCRnB = 0b0000011    (1$<$$<$CSn1) | (1$<$$<$CSn0) \\ 

     \texttt{ 256 } & TCCRnB = 0b0000100   (1$<$$<$CSn2) \\ 

     \texttt{ 1024 } & TCCRnB = 0b0000101  (1$<$$<$CSn2) | (1$<$$<$CSn0) \\ 

    \hline
    \end{tabular}
    \end{center}
  Timer1 control register uses STS not OUT !

\emph{ Set prescalar to 1024 for timer1 }
  -----
    ldi temp, 1$<$$<$CS12 | 1$<$$<$CS10
    sts TCCR1B, temp
  ,,,,

\emph{ Set prescalar to 64 for timer1 }
  -----
    ldi temp, 1$<$$<$CS11 | 1$<$$<$CS10
    sts TCCR1B, temp
  ,,,,

  Timer2 has more prescaler values which gives more flexibility for
  the frequencies generated.


  \arrayrulecolor{gray}
  \begin{center}
  \begin{tabular}{ |rl| }
    \multicolumn{2}{c}{\textbf{ prescalar values for timer2  }} \\
  \hline

     \texttt{ 1 } & TCCR2B = 0b0000001     (1$<$$<$CS20) eg: ldi temp, 1$<$$<$CS20 \\ 

     \texttt{ 8 } & TCCR2B = 0b0000010     (1$<$$<$CS21) \\ 

     \texttt{ 32 } & TCCR2B = 0b0000011    (1$<$$<$CS21) | (1$<$$<$CS10) \\ 

     \texttt{ 64 } & TCCR2B = 0b0000100   (1$<$$<$CS22) \\ 

     \texttt{ 128 } & TCCR2B = 0b0000101  (1$<$$<$CS22) | (1$<$$<$CS10) \\ 

     \texttt{ 256 } & TCCR2B = 0b0000110   \\ 

     \texttt{ 1024 } & TCCR2B = 0b0000111   \\ 

    \hline
    \end{tabular}
    \end{center}
\emph{ Set the prescaler }
  \begin{lstlisting}
    ldi r16, 0b00000011    ; set timer prescaler = 64
    out TCCR0B, r16        ; timer control register B
  \end{lstlisting}

\subsection{Calculate Delays}

  This is confusing. Just use Freq=1/Period and the usual Freq formula

  Delays are easy! How many clocks per second? That clock frequency
  / prescalar. Now, how many clocks until overflow or compare/match?
  Divide the second by the first and that is the time delay.
  An the wave frequency is just 1/(2*time delay)  2* because square
  wave has high then low.

\emph{ Calculate the delay generated by timer0 }
  for example:
    Time for each square wave =
       2 (on/off state) * 
       (ticks-until-overflow + instruction cycles) * prescalar
       / xtal (crystal frequency) 

    ticks-until-overflow is 255-TCNT0+1
    instruction cycles is sum of each instruction clock cycles

  For example 9.3 (TCNT0=0xf2) the delay calculation is (on atmega328 16 Mhz)
    T = 2 * (14 + 24) * 1 / 16 Megaherz 
      = 2 * 38 / 16 Megaherz 
      = 38 / 8000000 seconds
      = 38000000/8000000 microseconds
      = 38/8 useconds  
   Frequency = 1/T = 8000000/38 Hz = 210.526 kHz
     
  In forth  ``14 24 + 2 * 100 * 16 /'' gives the period in microseconds
  to 2 decimal places

  With prescaler=1024 and TCNT0=0xf2 the delay calculation is
  (atmega328 16 Mhz) in forth
    no this gives an overflow in a 16 bit forth!!
    14 24 + 2 * 100 * 1024 * 16 /  (30.72 microseconds)
    Freq= 1/T = 100000000 / 3072 = 32.552 kHz ?? no
           it should be 206 Herz  (A440 is 440 herz)

\subsection{Timer Two}

  Timer2 has more prescale values than timer0, but is 8 bit
  This would allow better approximations for some tones (eg: use prescale 128
  for A440).

BLINKING TIMERS ...

\emph{ Blinks a led using the timer0 (counter) with prescaler }
  \begin{lstlisting}
  ; blinks an LED which is connected to PB5 (digital out 13)

  .include "m328Pdef.inc"
  .def temp = r16
  .cseg
  .org 0

  rjmp start
  start:

    ; freq = Fosc / (N*top)
    ; freq = 16000000/(1024*256) = 61.035 hz
    ; this is the minimum frequency for timer0 and timer2
    ; find sleep time
    ;   sleep time = period = 1/freq = 1/61,035 = 16ms 
    
    sbi DDRB, 5           ; set portb, bit 5 for output
    ldi temp, 0 | 1<<CS02 | 1<<CS00  ; set 1024 prescalar (16Mhz/1024)
    out TCCR0B, temp                 ; loading the clock starts the timer
    
  again:
    sbi PORTB, 5   ; turn on bit5, on-board led at pin 13
    rcall sleep    ; sleep more to make it visible 
    rcall sleep
    rcall sleep
    cbi PORTB, 5      ; turn off portb,5 output 
    rcall sleep
    rcall sleep
    rcall sleep
    rjmp again

  ; sleep for 16ms, but shouldnt we stop and start the timer here? 
  sleep:
    in r16, TIFR0          ; get timer flags register 0
    andi r16, 0 | 1<<TOV0  ; tov0 ~ timer overflow flag (bit 2) 
    breq sleep             ; if overflow not set, then loop
    ldi r16, 0 | 1<<TOV0   ; reset timer overflow flag by setting it
    out TIFR0, r16         ; to 1
    ret
  
  \end{lstlisting}

  If we preload the counter with eg 128 then the timer overflows
  twice as quickly. TCNT0 allows different delays to be generated
  not just fosc/n. 

\emph{ Preload the timer counter }
  \begin{lstlisting}
    ldi r16, 128        ; preload timer with 128
    out TCNT0, r16      ; timer count register := 128
  \end{lstlisting}

\emph{ Blinking a led with timer/counter0 with prescaler and preloaded counter }
  \begin{lstlisting}
  ; LED connected to PB5 (digital out 13)

  .nolist
  .include "m328Pdef.inc"
  .list
    .def temp = r16
  .dseg
  .cseg
    .org 0
    rjmp start
    ; ISRs can go here

  sleep:
    in temp, TIFR0          ; get timer flags register 0
    andi temp, 0 | 1<<TOV0  ; tov0 ~ timer overflow flag (bit 2) 
    breq sleep              ; if overflow not set, then loop
    ldi temp, 1<<TOV0       ; reset timer overflow flag by setting it
    out TIFR0, temp         ; to 1
    ret

  start:

    sbi DDRB, 5           ; ddrb ~ data direction register B, bit5 output
    ldi temp, 0 | 1<<CS02 | 1<<CS00  ; values for 1024 prescalar
    out TCCR0B, temp                 ; loading the clock starts the timer
    
  again: 

    ldi r16, 128        ; preload timer with 128
    out TCNT0, r16
    sbi PORTB, 5        ; set bit 5 in portb, turn on led
    rcall sleep
    cbi PORTB, 5        ; set bit 5 in portb, turn off led
    rcall sleep
    rjmp again

  \end{lstlisting}

  By using interrupts the avr is free to do other things
  The code below demonstrates the important technique of 
  implementing an interrupt handler.

  The code below is incorrect. The vector address is wrong. Use isr 
  vector address names, not numbers.

\emph{ Toggle led using timer0 interrupt  }
  ---------

  .nolist
  .include ``m328Pdef.inc''
  .list
    .def a = r16        ;general purpose accumulator
  .dseg
  .cseg
  .org 0000
    rjmp onreset        ; reset vector
  .org 0003
    rjmp TIM0\_OVF       ; timer0 overflow handler

  onreset:
    sbi DDRB, 0           ; set portb0 for output
    ldi a, 0b00000101     ; set prescaler to /1024, use bitnames!
    out TCCR0B, a         ; timer/counter control register "b"
    ; enable timer-overflow interupt
    ldi a, 1$<$$<$TOIE0       ; another way to write the same thing
                          ; toie0 timer 0 overflow interrupt enable

    ; On the atmega328 use ``sts'' not ``out'' for TIMSK0 
    ; sts = store direct to data space
    sts TIMSK0, a         ; timer interrupt mask register 
    sei                   ; enable interupts globally

  ; timer0 overflow interrupt handler, can name this anything
  tim0\_ovf:
    ldi r20, 1
    eor PORTB, r20        ; toggle the 0 bit
    reti

  ; main loop
  start:
    nop                ;do nothing
    rjmp start 
    
  ,,,

TIMER0

  Example 9.3 from Mazidi
  We need more examples from Mazidi using an interrupt with a timer.

  The example below suggests the idea of using an LED to ``see'' 
  an audio signal (samples read from a table and emitted with PWM
  varying the duty cycle in an interrupt.

\emph{ Generate a very short delay using timer0 and toggle led on pb5 }
  \begin{lstlisting}
  .include "m328Pdef.inc"
  
  .macro  initstack
    ldi r20, high(ramend)
    out SPH, r20
    ldi r20, low(ramend)
    out SPL, r20
  .endmacro
    
    initstack
    ldi r16, 1<<5      ; toggle bit for portb,5
    sbi DDRB, 5        ; portb,5 is output (pin 13 LED on an arduino)
    ldi r17, 0       
    out PORTB, r17    ; turn off all of portb 
  begin:
    rcall delay  
    eor r17, r16      ; xor toggle
    out PORTB,r17     ; toggle value on portb,5 (pin13 arduino)
    rjmp begin
    
  delay:
    ldi r20, 0xf2    ; too fast to be audible/ but visible with LED
    out TCNT0, r20   ; preload timer0 with 0xf2
    ldi r20, 0x01    ; wave form mode ???
    out TCCR0A, r20  ; 
    ldi r20, 0x01    ; timer/counter control register b
    out TCCR0B, r20  ; timer0 normal mode, internal clock, no prescale
  again:  
    in r20, TIFR0     ; read timer0 interrupt flag register
    sbrs r20, TOV0    ; just wait until overflow
    rjmp again
  
    ldi r20, 0x0
    out TCCR0B, r20    ; stop timer 0
  
    ldi r20, (1<<TOV0)   ; clear timer overflow flag
    out TIFR0, r20       ; set to 1 to clear (!)
    ret
  \end{lstlisting}

TIMER0 AND PIEZO TONES ....

  Using a prescalar we can reduce the frequency of timer0 overflows
  sufficiently to generate audio tones.

\subsection{Compare Match Mode}

  In this mode we can trigger an event when the counter reaches
  a certain value
  
  The following needs to be adapted to the atmega328

\emph{ Using compare match mode }
  \begin{lstlisting}
  .include "m328Pdef.inc"  
  
  .macro initstack
    ldi r16,high(ramend)
    out SPH,r16
    ldi r16,low(ramend)
    out SPL,r16
  .endmacro
    
    initstack
    ldi r16,0x08
    sbi DDRB,3      
    ldi r17,0    
  begin:  
    out portb,r17    
    rcall delay
    eor r17,r16      
    rjmp begin
  
  delay:
    ldi r20,0
    out TCNT0, r20    ; load counter with zero
    ldi r20, 9         ; the value to compare to
    out OCR0A, r20    ; timer output compare register
  
    ldi r20,0x09
    out TCCR0A, r20     
  again:  
    in r20, TIFR0
    sbrs r20, OCF0  
    rjmp again
    ldi r20, 0x0
    out TCCR0, r20    ; stop timer
    ldi r20, 1<<OCF0   ;  
    out TIFR0, r20      ; 
    ret
  ,,,,

INTERRUPT IN CTC MODE FOR TIMER0 ....

  We can check these values with a piezo speaker and a guitar
  tuning app.

  Frequency calculations for all Timers (CSn values different for Timer2):
    prescaler = 1024 + match value = 40
    freq = 16Mhz / 1024 / 40  = 15625/40 = approx 390.5 Hz
    *2 for high low wave

  Questions: is 16MHz 2^16 or 16000000 ? 

  I think the answer is timer0 control registers are not 
  memory mapped!! so use OUT not STS to load them. 

  This was not working because I was using STS instead of OUT
  to load the control registers for timer0

  Probably get better accuracy with a lower prescalar
   freq: Solve for 440 Hz (tone A440 or A4)
   440 = 16000000/( 1024 * 2(n+1))
   440*1024*2 = 16000000 / (n+1)
   n+1 = 16000000/(880*1024) = 17.75
   n = approx 17
   n+1 = 16MHz / (1024 * 2 * T(freq) )
   Check with piezo and guitar tuner!
   

  * CTC interrupts make an <n> Hz square wave on 16Mhz chip for Timer0
  --------
  .include "m328Pdef.inc"
      
    ; we use PORTB.5 which is arduino pin 13 with on board LED 
    ; portb.0 is arduino pin 8
    ; portd.0 is arduino pin 0

    ; to create a 440 herz square wave we need to toggle at 880 herz
    ; (since a wave consists of a high and low part of equal duration)
    ; Better to use the minimum prescalar eg
    ;    freq = Fosc/(2*N*top)
    ;     440 = 16000000/(2*256*top)  
    ;     top = 16000000/(2*256*440) = 71
    ;  "freq" refers to the frequency of the square wave and NOT the 
    ;  frequency of the interrupt (which is double)
    ;
    .def zero = r2
    .def temp = r18 

  .dseg
  .cseg
  .org 0x0
    rjmp main 
  .org OC0Aaddr    ; timer0 compare match interrupt vector
    jmp timerMatch 
  main:
                  ; assume auto stack init
    clr zero      ; set register := 0 and dont change it!
    sbi DDRB, 5   ; make portB.5 output (arduino pin13 led)
  begin:
    ; wgm01 ctc "clear timer on compare" mode 
    ldi temp, 1<<WGM01
    out TCCR0A, temp       ; ctc compare/match timer mode 
    ldi temp, 71           ; gives approx 440 Hz square wave on 16Mhz chip 
                           ; with /256 prescalar 
    out OCR0A, temp        ; load compare value 40 

    ; enable the ctc interrupt, put the toggle in the isr
    ; note: WGMnn values different for different timers!
    ldi temp, 0 | (1<<OCIE0A)
    sts TIMSK0, temp ; enable compare/match interrupt
    sei              ; global enable interupts
    ldi temp, 1<<CS02   ; clock set value for 256 prescalar
    out TCCR0B, temp    ; loading the clock starts the timer

  here:
    ; micro can do other work here. Its not tied up!
    rjmp here

  timerMatch:
    ; this interrupt is actually unnecessary in this case because we 
    ; could use the toggle mode of the timer, but maybe not for this pin.
    ; interrupt automatically clears the compare/match flag OCF0A
    sbic PINB, 5    ; skip next if bit5 (ard pin 13) is clear. 
    cbi PORTB, 5    ; turn off led/wave
    sbis PINB, 5    ; skip next if bit5 is set
    sbi PORTB, 5    ; turn on led/wave
    reti

   \end{lstlisting}
   
  Also not working...

\emph{ C code for timer0 interrupt }
  \begin{lstlisting}
   // this code sets up a timer0 for 4ms @ 16Mhz clock cycle
   // an interrupt is triggered each time the interval occurs.
   #include <avr/io.h> 
   #include <avr/interrupt.h>


   int main(void)
   {
      DDRB |= (1 << 5); // Set LED as output
      // Set the Timer Mode to CTC
      TCCR0A |= (1 << WGM01);
      // Set the value that you want to count to
      OCR0A = 0xF9;

      TIMSK0 |= (1 << OCIE0A);    //Set the ISR COMPA vect
      sei();         //enable interrupts
      TCCR0B |= (1 << CS02);
      // set prescaler to 256 and start the timer

      while (1)
      {
      //main loop
      }
    }

    ISR (TIMER0_COMPA_vect)  // timer0 overflow interrupt
    {
    //event to be exicuted every 4ms here
        PORTB ^= (1 << 0); // Toggle the LED
        PORTB ^= (1 << 5); // Toggle the LED
    }

  \end{lstlisting}

TOGGLE IN CTC MODE FOR TIMER0 ....

  OC0A = PD6, OC0B = PD5 So we connect our led here when toggling.
  
  In the automatic mode we can dispense with the interrupt altogether.
  So we dont need to enable interrupts, or write an ISR.

  In timer0 set automatic set/clear/toggle of output pin.
  COM0A1:COM0A0 bits in Timer0 control register TCCR1A. 

  Output pins are fixed in toggle mode, see the table above
  oc1a is arduino pin 9

\emph{ C code to initiate timer1 in output toggle mode }
\begin{lstlisting}
  TCCR0A |= (1 << COM0A0);
\end{lstlisting}

\emph{ Assembly code to enable timer0 output toggle }
  -------
    ldi temp, 1$<$$<$COM0A0     ; enable Timer0 output pin toggle 
    sts TCCR0A, temp
    ; or use out for the atmega328 
    out TCCR0A, temp
  ,,,

  The output toggle below must be connected to pin PD6 (PORTD, 6)
  because this is the hardware output pin for Timer0 channel A
  We can see this from the ``pin out'' diagram of an Atmega328p chip.
  The output pin of Timer0, channel A is labelled OC0A.

  The code below is the most succinct way to create a square wave or 
  or drive a piezo speaker. It will probably not dim a led much,
  and the flashing of the LED may not be visible. Use PWM to dim leds.

   Use OUT, not STS for Timer0 (for timers 1 \& 2 used STS because they
   are memory mapped!)

  OCR0A value for C4=262 Hz
    n+1 = 16MHz / (256 * 2 * T(freq) )
    n+1 = 16000000 / (512 * 262)
    n $<$$>$ 118 

\emph{ Timer0 CTC mode output toggle with 262Hz wave on 16Mhz chip  }
  --------
  .include ``m328Pdef.inc''
    ; connect LED/piezo to Arduino digital pin 6
    ; look at pinout of atmega328 to see output pin of timer0 
    .def zero = r2
    .def temp = r18 

  .dseg
  .cseg
  .org 0x0
    rjmp main 
  main:
    ; assume stack pointer is auto initialised
    clr zero               ; set register := 0 and dont change it!
    sbi DDRD, 6            ; make portD.6 output (arduino pin6)
  begin:
    ldi temp, 118         ; gives Tone C4 (262 Hz) square wave on 16Mhz chip 
                          ; with /256 prescalar. Tone C4= 261.63hz well-tempered 
    out OCR0A, temp       ; load compare value 
    ldi temp, 1$<$$<$COM0A0 | 1$<$$<$WGM01  ; enable Timer0 output pin toggle 
                                    ; and clear-timer-on-compare mode ``ctc''
    out TCCR0A, temp
    ; no interrupts needed.
    ; bit names for portability and readability
    ; wgm01:00=0b10 (``ctc'' mode), CS02:00=0b100 (clock/256 prescaler)
    ldi temp, 1$<$$<$CS02  ; prescalar = 256  Clock Select bits
    out TCCR0B, temp   ; loading the clock starts the timer
                       ; stop the timer by loading 0 into CS bits 
  here:
    ; micro can do other work here. Its not tied up!
    rjmp here
   ,,,
   
\subsection{Timer One}

  The atmega328 has 3 timer/counters. Timer1 is the second and is a 16 bit
  counter, so can count from 0 to 64K. This is useful for producing ``visible''
  delays, that is, delays that can be seen when toggling an led, for example.
  The 8 bit timer delays tend to be in the milliseconds even when using the
  maximum prescaler.

\emph{ One millisecond delay with timer1 }
  --------
  .include ``m328Pdef.inc''
  .def zero = r19
  .def temp = r20
  .dseg    
  .cseg
  .org 0
    rjmp main

  main:
    clr zero     ;  set register to 0 and dont change
    ldi r16, high(ramend)  
    out SPH, r16
    ldi r16, low(ramend)
    out SPL, r16

    sbi DDRB, 5    
  begin:
    sbi portb, 5    
    rcall delay1milli
    cbi portb, 5    
    rcall delay1milli
    rjmp begin
  
  delay1milli:
    ldi r20, high(65536-8000)
    sts TCNT1H, r20         ; timer1 counter reg (high byte)
    ldi r20, low(65536-8000)
    sts TCNT1L, r20         ; timer1 counter reg (low byte)
  
    ldi r20, 0x0
    sts TCCR1A, r20    
    ldi r20, 0x1
    sts TCCR1B, r20    
  again:  
    in r20, TIFR1     ; check if overflow has occurred
    sbrs r20, TOV1    ; if so, exit loop
    rjmp again        ; if not, wait and check
    ldi r20, 1$<$$<$TOV1  ; reset the overflow flag by setting to 1 
    out TIFR1, r20    
    sts TCCR1B, zero    
    sts TCCR1A, zero    
    ret  
  ,,,

  example 9.33 from mazidi

  The actual delay time below is 0.25 of a second. So the 
  square wave period is 0.5 seconds and frequency= 1/period = 2Hz

  This is ``Normal'' mode, so the timer does not reset when
  it gets to the compare value, but we can still poll the compare 
  flag in normal mode (and maybe even spark an interrupt on compare?)
  So it is a kind of fake CTC mode (clear timer on compare)

\emph{ Make a 2Hz square wave on 16Mhz chip with normal mode. Polls compare flag }
  --------
  .include ``m328Pdef.inc''
      
    ; ``zero'' should make code more readable
    ; we use PORTB.5 below because arduino boards often have
    ; an led on the board at that pin (pin 13)
    ; Code below working on arduino uno 16MHz but flashes twice 
    ; per second
    .def zero = r2
    .def temp = r18 

  .dseg
  .cseg
   rjmp main 
   main:
     clr zero               ; set register := 0 and dont change it!
     ldi temp, high(ramend) ; set up the stack
     out SPH, temp 
     ldi temp, low(ramend)
     out SPL, temp 
     sbi DDRB, 5      ; make portB.5 output (arduino pin13)
   begin:
     sbi PORTB, 5     ; turn on LED (high signal)
     rcall delay  
     cbi PORTB, 5     ; clear bit: turn off LED 
     rcall delay  
     rjmp begin
   
   delay:
     ; actually delay time is 1/4 second.
     ldi r20, high(62500-1) ; gives 2Hz square wave on 16Mhz chip 
                            ; with /64 prescalar 
     sts OCR1AH, r20        ; load compare value (62500) high byte
     ldi r20, low(62500-1)
     sts OCR1AL, r20     ; load compare value (62500) low byte
     sts TCNT1H, zero    ; set counter to 0  (high+low bytes)
     sts TCNT1L, zero    
     sts TCCR1A, zero   ; 
     ; better to use bit names here
     ; wgm13:12=00, normal mode, CS11:10=0b11 (i.e clock/64)
     ldi r20, 0 | (1$<$$<$CS11) | (1$<$$<$CS10)
     sts TCCR1B, r20   ; loading the clock starts the timer
   checkflag:  
     in r20, TIFR1     ; check timer compare/match flag in TIFR1
     sbrs r20, OCF1A   ; OCF1A is the compare/match  flag
     rjmp checkflag    ; keep polling
     ldi r20, 1$<$$<$OCF1A ; reset the match flag, by writing 1
     out TIFR1, r20    ; write to the timer1 flag register 
     sts TCCR1B, zero
     sts TCCR1A, zero   ; stop the timer
     ret  
   ,,,

TIMER1 CTC CLEAR TIMER ON COMPARE MODE ....

  modify the code above to use CTC and then an interrupt

  The code below is simpler than the above because we do not have 
  to reset the counter, nor do we have to stop the timer/counter.
  Even simpler is an interrupt. Using an interrupt the compare/match
  flag is automatically cleared.

\emph{ 2Hz wave on 16Mhz chip Timer1 in CTC mode, polling compare/match flag }
  --------
  .include ``m328Pdef.inc''
      
    ; ``zero'' should make code more readable
    ; we use PORTB.5 below because arduino boards often have
    ; an led on the board at that pin (pin 13)
    ; Code below working on arduino uno 16MHz but flashes twice 
    ; per second
    .def zero = r2
    .def temp = r18 

  .dseg
  .cseg
   rjmp main 
   main:
     clr zero               ; set register := 0 and dont change it!
     ldi temp, high(ramend) ; set up the stack
     out SPH, temp 
     ldi temp, low(ramend)
     out SPL, temp 
     sbi DDRB, 5      ; make portB.5 output (arduino pin13)
   begin:
     ; actually delay time is 1/4 second.
     ldi temp, high(62500-1) ; gives 2Hz square wave on 16Mhz chip 
                             ; with /64 prescalar 
     sts OCR1AH, temp        ; load compare value (62500) high byte
     ldi temp, low(62500-1)
     sts OCR1AL, temp        ; load compare value (62500) low byte
     sts TCCR1A, zero     ; no configuration
     ; use bit names for portability and readability
     ; wgm13:12=01 (ctc mode), CS11:10=0b11 (i.e clock/64)
     ldi temp, 0 | 1$<$$<$CS11 | 1$<$$<$CS10 | 1$<$$<$WGM12
     sts TCCR1B, temp   ; loading the clock starts the timer

  checkflag:
     in r20, TIFR1     ; check timer compare flag in TIFR1
     sbrs r20, OCF1A   ; OCF1A is the compare flag
     rjmp checkflag    ; keep polling
     ldi r20, 1$<$$<$OCF1A ; reset the compare/match flag, by writing 1
     out TIFR1, r20    ; write to the timer1 flag register 

     sbic PINB, 5    ; toggle portb.5 (pin 13 arduino)
     cbi PORTB, 5   
     sbis PINB, 5  
     sbi PORTB, 5 
     rjmp checkflag

   ,,,

  Working 2 august 2018

\emph{ Ctc interrupts make 2Hz wave on 16Mhz chip Timer1 }
  --------
  .include ``m328Pdef.inc''
      
    ; we use PORTB.5 is arduino pin 13 with on board LED 
    ; portb.0 is arduino pin 8
    ; portd.0 is arduino pin 0
    .def zero = r2
    .def temp = r18 

  .dseg
  .cseg
  .org 0x0
    rjmp main 
  .org OC1Aaddr    ; timer1 compare match interrupt
    jmp timer1match 
  main:
    clr zero               ; set register := 0 and dont change it!
    ldi temp, high(ramend) ; set up the stack
    out SPH, temp 
    ldi temp, low(ramend)
    out SPL, temp 
    sbi DDRB, 5             ; make portB.5 output (arduino pin13 led)
  begin:

    ; actually delay time is 1/4 second.
    ldi temp, high(62500-1) ; gives 2Hz square wave on 16Mhz chip 
                            ; with /64 prescalar 
    sts OCR1AH, temp        ; load compare value (62500) high byte
    ldi temp, low(62500-1)
    sts OCR1AL, temp        ; load compare value (62500) low byte
    sts TCCR1A, zero        ; no configuration

    ; enable the ctc interrupt, put the toggle in the isr
    ldi temp, 1$<$$<$OCIE1A
    sts TIMSK1, temp ; enable compare/match interrupt
    sei              ; global enable interupts

    ; use bit names for portability and readability
    ; wgm13:12=01 (``ctc'' mode), CS11:10=0b11 (clock/64 prescaler)
    ldi temp, 0 | 1$<$$<$CS11 | 1$<$$<$CS10 | 1$<$$<$WGM12
    sts TCCR1B, temp   ; loading the clock starts the timer

  here:
    ; micro can do other work here. Its not tied up!
    rjmp here

  timer1match:
    ; interrupt automatically clears the compare/match flag OCF1A
    sbic PINB, 5    ; toggle portb.5 (pin 13 arduino)
    cbi PORTB, 5    ; turn off led/wave
    sbis PINB, 5  
    sbi PORTB, 5    ; turn on led/wave
    reti

   ,,,
   
\emph{ C code for timer1 ctc mode with an interrupt  }
    \begin{lstlisting}
    #include 
    #include 
    int main (void)
    {
      DDRB |= (1 << 0);       // Set LED as output
      TCCR1B |= (1 << WGM12); // Configure timer 1 for CTC mode
      ; but TIMSK is TIMSK1 in Assembly!! 
      TIMSK |= (1 << OCIE1A); // Enable CTC interrupt
      sei();                  //  Enable global interrupts
      OCR1A   = 15624;        // Set CTC compare value to 1Hz at 
                              // 1MHz AVR clock, with a prescaler of 64
      TCCR1B |= ((1 << CS10) | (1 << CS11)); // Start timer at Fcpu/64
      for (;;)
      {
        // do other work here
      }
    }
    
    ISR(TIMER1_COMPA_vect)
    {
      PORTB ^= (1 << 0); // Toggle the LED
    }

    \end{lstlisting}

TOGGLE IN CTC MODE FOR TIMER1 ....

  In the automatic mode we can dispense with the interrupt altogether.
  So we dont need to enable interrupts, or write an ISR.

  In timer one set automatic set/clear/toggle of output pin.
  COM1A1:COM1A0 bits in Timer1 control register TCCR1A

  I am not sure where to find output pins, but oc1a is arduino pin 9
  = output pins for automatic toggle 
  .. PB3 = OC0 - timer0 output pin (arduino pin ?)
  .. PD4 = OC1B - timer1 channel B pin (arduino pin ?)
  .. PD5 = OC1A - timer1 channel A outpin (arduino pin 9)
  ..

\emph{ C code to initiate timer1 in output toggle mode }
\begin{lstlisting}
  TCCR1A |= (1 << COM1A0);
\end{lstlisting}

\emph{ Assembly code to enable timer1 output toggle }
  -------
    ldi temp, 1$<$$<$COM1A0     ; enable Timer1 output pin toggle (channel A)
    sts TCCR1A, temp
  ,,,

  The output toggle below must be connect to PB1 (arduino pin 9)
  because this is the hardware output pin for Timer1 channel A
 
  The code below is the most succinct way to create a square wave/ toggle
  an LED, or drive a piezo speaker. 
  
  We could develop this sketch, by storing
  the match value in a data variable in dseg, and then reading the serial 
  connection for keystrokes. When a keystroke is detected, the match value
  is altered, so that the tone emited by the piezo, or the led flash rate,
  is changed. This would create a very simple piezo ``keyboard''. 

\emph{ Ctc output toggle with 2Hz wave on 16Mhz chip Timer1 }
  --------
  .include ``m328Pdef.inc''
    ; working 2 august 2018 
    ; connect LED to PB1, arduino pin 9 
    ; portb.0 is arduino pin 8
    ; portd.0 is arduino pin 0
    .def zero = r2
    .def temp = r18 

  .dseg
  .cseg
  .org 0x0
    rjmp main 
  main:
    clr zero               ; set register := 0 and dont change it!
    ldi temp, high(ramend) ; set up the stack
    out SPH, temp 
    ldi temp, low(ramend)
    out SPL, temp 
    sbi DDRB, 1             ; make portB.1 output (arduino pin9)
  begin:
    ; actual delay time is 1/4 second.
    ldi temp, high(62500-1) ; gives 2Hz square wave on 16Mhz chip 
                            ; with /64 prescalar 
    sts OCR1AH, temp        ; load compare value (62500) high byte
    ldi temp, low(62500-1)
    sts OCR1AL, temp        ; load compare value (62500) low byte

    ldi temp, 1$<$$<$COM1A0     ; enable Timer1 output pin toggle (channel A)
    sts TCCR1A, temp

    ; no interrupts needed.
    ; bit names for portability and readability
    ; wgm13:12=01 (``ctc'' mode), CS11:10=0b11 (clock/64 prescaler)
    ldi temp, 0 | 1$<$$<$CS11 | 1$<$$<$CS10 | 1$<$$<$WGM12
    sts TCCR1B, temp   ; loading the clock starts the timer

  here:
    ; micro can do other work here. Its not tied up!
    rjmp here

   ,,,
   
  Timer1 prescaler
\begin{lstlisting}
  CS12:11:10 = 0b101 (prescaler = 1024 the maximum)
\end{lstlisting}

\emph{ Drive a piezo at 400Hz with output toggle on timer1  }
  --------
  .include ``m328Pdef.inc''
    ; working 2 august 2018 
    ; connect LED to PB1, arduino pin 9 
    ; portb.0 is arduino pin 8
    ; portd.0 is arduino pin 0
    .def zero = r2
    .def temp = r18 

  .dseg
  .cseg
  .org 0x0
    rjmp main 
  main:
    clr zero               ; set register := 0 and dont change it!
    ldi temp, high(ramend) ; set up the stack
    out SPH, temp 
    ldi temp, low(ramend)
    out SPL, temp 
    sbi DDRB, 1             ; make portB.1 output (arduino pin9)
  begin:
    ; actual delay time is 1/4 second.
    ldi temp, high(40-1) ; gives 2Hz square wave on 16Mhz chip 
                            ; with /64 prescalar 
    sts OCR1AH, temp        ; load compare value (62500) high byte
    ldi temp, low(40-1)
    sts OCR1AL, temp        ; load compare value (62500) low byte

    ldi temp, 1$<$$<$COM1A0     ; enable Timer1 output pin toggle (channel A)
    sts TCCR1A, temp

    ; no interrupts needed.
    ; bit names for portability and readability
    ; wgm13:12=01 (``ctc'' mode), CS12:11:10=0b101 (clock/1024 prescaler)
    ; frequency = 16 MHz/ 1024 / 40 = approx 400 Hz (audible tone)
    ldi temp, 0 | 1$<$$<$CS12 | 1$<$$<$CS10 | 1$<$$<$WGM12
    sts TCCR1B, temp   ; loading the clock starts the timer

  here:
    ; micro can do other work here. Its not tied up!
    rjmp here

   ,,,
   
\subsection{Ctc Clear Timer On Compare Mode}
    
   This is poor code because it doesnt use bit names for
   the control registers.

\emph{ Clear timer on compare for attiny13 }
   \begin{lstlisting}

   .include "tn13def.inc"   ;(attiny13 definitions)
     .def A = r16           ;general purpose accumulator
   .org 0x00
   main:
     sbi DDRB, 0          ;set portb0 for output
     ldi A, 0b01000010    ;activate ctc mode
     out TCCR0A, A        ;set flag on compare match
     ldi A, 0b00000101    ;            
     out TCCR0B, A         ;set prescaler to /1024
     ldi A, 128            ;our compare value
     out OCR0A, A          ;into the compare register

     here:
       ; this line seems dodgy! need to EOR the portB no??
       sbi PINB, 0    ;flip the 0 bit
       rcall pause    ;wait
       rjmp here      ;go back and do it again

     pause:          
     ploop: 
       in   a, TIFR0      ;wait for timer
       andi a, 0b00000100 ;(ocf0a)
       breq ploop
       ldi a, 0b00000100  ;clear flag
       out tifr0, a       ;note: write a 1 (not 0)
       ret

    \end{lstlisting}

TIMER1 INTERRUPTS ....
  
  compare/match a, compare/match b, overflow, capture event.

\section{Delays}

  It is a surprisingly common task to do nothing for a short period of 
  time. MCUs are often too fast (16Mhz !!) and need to be slowed down.
  
\emph{ Blink on-board led using an approximate 1/2 second delay loop }
  \begin{lstlisting}
  ;  turns on an LED which is connected to PB5 (digital out 13)

  ; testing
  ; with r18=40 flashed 20 times in about 18.73 seconds (too fast)
  ; with r18=45 flashed 30 times in about 32 seconds (too slow)
  ; with r18=42 flashed 20 times in about 19.52 seconds (not bad) 

 .nolist
 .include "m328Pdef.inc"
 .list
 .dseg
 .cseg
 .org 0
   sbi DDRB, 5      ; data direction register for portB, bit5 is output

  main:
   sbi PORTB, 5     ; turn on bit5 in port b (pin 13 arduino)
   rcall delay
   cbi PORTB, 5     ; clear bit5, turn off led
   rcall delay 

  rjmp main

  ; An approximate half second delay
  delay:
    ; to calculate accurately the delay here involves looking
    ; at the number of cycles for each instruction.
    clr r16            ; set reg16 := 0
    clr r17
    ldi r18, 42 
    here:              ; a delay loop 42*256^2 instructions
      dec r16          ; 
      brne here 
      dec r17
      brne here 
      dec r18
      brne here 
    ret
  \end{lstlisting}

 Apparently the arduino ``millis'' function uses timer0

\emph{ Use timer0 for 1millisecond delay  }
 \begin{lstlisting}
 .nolist
 .include "m328Pdef.inc"
 .list
 .dseg
 .cseg
 .org 0
   rjmp start
 start:
   sbi DDRB, 5      ; data direction register for portB, bit5 is output
 
 \end{lstlisting}

\section{Ports}

\subsection{Toggling Ports}

  A common passtime is to toggle the output on a port (although ``pwm''
  and ``ctc'' modes of the timer/counters (0,1,2) can do this automatically)
  
\emph{ Toggle value on a port }
  -------
    in temp, PORTB ; not PINB
    ldi temp2, \$01 ; bit 0
    eor temp, temp2
    out PORTB, temp
  ,,,
  
\emph{ Another way... }
  ---------
    sbic pinb, 0    ;1 or 2clocks if bit 0 clear, skip next line
    cbi portb, 0    ;2 if 1, execute this line
    sbis pinb, 0    ;1-2 clocks if bit 0 high, skip next line
    sbi portb, 0    ;2 if 0, execute this line
  ,,,

\emph{ A cumbersome way to toggle, but maybe useful elsewhere }
  \begin{lstlisting}
     cpi flag, 0
     breq zeroflag     ; 
     clr flag
     sbi PORTB, 5      ; turn on LED (high signal)
     rjmp checkflag
   zeroflag:
     cbi PORTB, 5      ; turn on LED (high signal)
     inc flag
   \end{lstlisting}

\section{Arduino}

\emph{ Install the arduino java software }
\begin{lstlisting}
  sudo apt-get install arduino
\end{lstlisting}

 Then select the serial device and board (eg duemilenove)
 Then select file/preferences and check box for verbose 
 info during upload

\emph{ Run arduino software with priviledges }
\begin{lstlisting}
  sudo arduino
\end{lstlisting}

 If you dont have the right priviledges the serial port
 will be greyed out.

\section{Compiling With Avra}

 Obtain a file called ``m328Pdef.inc''. This contains all the aliases
 or mnemonics for the atmega328. If you are using a different 
 avr chip obtain the appropriate file.

 remove the semi colon from the line
 ;.device ATmega328P

 This allows the compiler to check things like memory ranges
 and allows use of high(ramend) etc, eg for initializing the 
 stack.

\section{Uploading Code To The Arduino}

  The arduino, or any AVR chip with the arduino bootloader installed,
  contains a bootloader which checks for code to receive over a serial
  (usb...) connection when the MCU is reset. This is convenient because
  we do not need a ``ISP'' programmer to program the arduino.

\subsection{Command Line Upload}

 avrdude is the command line tool used to upload code to an arduino board.

 One trick is to select verbose output in the arduino IDE to 
 see the appropriate switches for avrdude for a given arduino board
 etc.

 The following details how to upload code, eg a hex file to 
 an arduino board from the unix command line.

 It doesnt seem to matter what usb socket the cable is 
 plugged into at all. (at least not on my linux mint machine)

\emph{ Upload to duemilenove arduino on linux }
\begin{lstlisting}
  sudo avrdude -v -v -v -v -p atmega328p -carduino -P/dev/ttyUSB0 -b57600 -D -Uflash:w:hello.hex:i
\end{lstlisting}

 Notice here the device and baud rate are different.

\emph{ Upload to ``uno'' compatible freetronics arduino board }
\begin{lstlisting}
  sudo avrdude -p atmega328p -carduino -P/dev/ttyACM0 -b115200 -D -Uflash:w:hello.hex:i
\end{lstlisting}

 If we use the wrong baud rate, avrdude gives messages, 
\begin{lstlisting}
  avrdude: stk500_recv(): programmer is not responding
\end{lstlisting}
\begin{lstlisting}
  avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x00
\end{lstlisting}

\emph{ The same without verbose output  }
\begin{lstlisting}
  sudo avrdude -p atmega328p -carduino -P/dev/ttyUSB0 -b57600 -D -Uflash:w:hello.hex:i
\end{lstlisting}

\emph{ Avrdude upload command for ``uno'' board connected via usb }
\begin{lstlisting}
  usr/share/arduino/hardware/tools/avrdude -C/usr/share/arduino/hardware/tools/avrdude.conf -v -v -v -v -patmega328p -carduino -P/dev/ttyACM0 -b115200 -D -Uflash:w:/tmp/build4770305616360723053.tmp/Blink.cpp.hex:i 
\end{lstlisting}

\emph{ Below is a typical avrdude command from the ide }
\begin{lstlisting}
  /usr/share/arduino/hardware/tools/avrdude -C/usr/share/arduino/hardware/tools/avrdude.conf -v -v -v -v -patmega328p -carduino -P/dev/ttyUSB0 -b57600 -D -Uflash:w:/tmp/build5695632546898703228.tmp/sketch_mar13a.cpp.hex:i 
\end{lstlisting}


  \arrayrulecolor{gray}
  \begin{center}
  \begin{tabular}{ |rl| }
    \multicolumn{2}{c}{\textbf{ avrdude options }} \\
  \hline

 \texttt{ -c the programmer } \\ 

 \texttt{ -P the serial port } \\ 

    \hline
    \end{tabular}
    \end{center}
\subsection{Problems Uploading}

\subsection{Serial Buffers Flooded}

  Flooding of the serial buffers is another cause of the ``not in sync'' error
  for avrdude (as below). This should only occur when  you have uploaded code
  to the arduino that reads/writes the usart serial connection. Perhaps first
  check other possible causes, such as a bad usb cable, arduino board wrongly
  specified, wrong baud rate etc etc.

  ----
    avrdude: stk500\_recv(): programmer is not responding
    avrdude: stk500\_getsync() attempt 3 of 10: not in sync: resp=0x00
  ,,,,

  Th techique below worked for me when all else had failed.

  John Wasser on forum.arduino.cc suggested the following solution
  for uploading a sketch/code when the serial buffers are flooded (by
  runaway serial usart read/write code)

  - Connect the arduino with a good usb cable to the computer
  - hold down the reset button on the arduino
  - keep holding down the reset button and disconnect the usb cable
    (this clears the computers usb buffers
  - reconnect the usb cable (still holding down the arduino reset button)
  - upload the sketch/code (for example to a duemilenova board
\begin{lstlisting}
  sudo avrdude -p atmega328p -carduino -P/dev/tty.usbserial-A8008Ghy -b57600 -D -Uflash:w:test.hex:i
\end{lstlisting}
  - as soon as the rx light on the arduino blinks, release the reset button.

\subsection{Not In Sync The Dreaded Error}

  The ``not in sync'' error prevents any new sketch or code being 
  uploaded from the arduino ide or from avrdude etc. It can be caused
  by a multitude of things... eg
  To solve, first check the arduino board type. Then check usb cable
  connections. Then check rx/tx pins not connected. Then swap out
  usb cable for different one. Then swap out board for different. 
  Etc. solution by elimination...

\emph{ Here is the dreaded not in sync error }
  -----
    avrdude: stk500\_recv(): programmer is not responding
    avrdude: stk500\_getsync() attempt 3 of 10: not in sync: resp=0x00
  ,,,,

   !! causes of out of sync error:
\emph{ The serial port is flooded and cannot receive the sketch/code }
        to upload. This is usually caused by code that reads/writes to
        the serial usart. See above for the solution.
\emph{ Serial port chosen badly. eg ttyS0 instead of ttyACM0 }
\emph{ Bad usb cable:  }
        For example: for a ``freetronics'' uno compatible, a good usb cable will
        light on board led, turn power led blue, flash onboard led,
        then flash rx led once, then flash D13 onboard led. A bad cable 
        may just turn on the power led blue, and turn on D13 led weakly.
\emph{ Bad ftdi cable connection }
\emph{ Wrong ``baud'' rate (if manually set with avrdude) }
\emph{ Wrong board type selected (eg uno when using pro mini) }
\emph{ Something plugged into the rx/tx serial pins of the board, }
         for example trying to upload a sketch by usb cable with
         an ftdi usb-to-uart connect plugged in
\emph{ A ``fried'' board or atmega chip, the worst scenario. }
\emph{ ... }

\section{Sound}

  http://avrprog.pbworks.com/w/page/9345379/AvrSound
    a good simple program to play midi file squeakily on a 
    piezo buzzer

  ideas: sin wave calculation. ding sound using decaying amplitude
  hilo tech sound file. exponential decay of amplitude for nice ding.
  fast pwm. see arduino book ``gunter''

\subsection{Sampled Sound}

   An internet comment
   "Just set up the AVR to do PWM at some multiple of the sample frequency and when the overlow interrupts occur reload the OCR for that timer's PWM with the next sample. As Bob suggests a 32K AVR will get you about 4 seconds of output (less because you need room for the player program itself)"

   The pcm format seems simple.
   8 bit unsigned 8000 samples per second wav file 
   hints: 
     Use Timer1 and timer0 (timer0 for loading new samples?)
     use CTC compare/match with fast pwm. fast pulse width
     modulation 8 bit. prescaler clk/2=8MHz (?)
     PWM frequency = 8MHz / (255 + 1) = 31.25kHz
     Use interrupts
     In the isr(timer0\_overflow.isr) just read the samples from
     the table and modify the ``duty cycle''

\emph{ Use sox to convert to 8bit 8000 samples per second, mono }
\begin{lstlisting}
  sox old.wav -r 8000 -c 1 -b 8 new.wav
\end{lstlisting}

   The spoken word ``microcontroller'' is about 11K in 8bit 8000 samples
   per second.

   http://avrpcm.blogspot.com/2010/11/playing-8-bit-pcm-using-any-avr.html
      Good step by step for arduino pcm audio 

\subsection{Music}
 
unsigned int notes[] = 
/*  Hap  py  Birth Day  to  you,  Hap py   birth day  to
    C4   C4   D4   C4   F4   E4   C4   C4   D4   C4   G4 */
  $\{$ 262, 262, 294, 262, 349, 330, 262, 262, 294, 262, 392,

/*  you, Hap py  Birth Day  dear  xxxx      Hap  py   birth
    F4   C4   C4   C5   A4   F4   E4   D4   B4b  B4b  A4 */
    349, 262, 262, 523, 440, 349, 330, 294, 466, 466, 440,

/*  day  to  you
    F4   G4   F4   */
    349, 392, 349 $\}$;

  Multiply by 2 to get the octave above. Eg A880 is octave above A440
  Use square waves (equal high low period)


  \arrayrulecolor{gray}
  \begin{center}
  \begin{tabular}{ |rl| }
    \multicolumn{2}{c}{\textbf{ some note frequencies in Herz }} \\
  \hline

   \texttt{ D } & 294 \\ 

   \texttt{ D\# } & 311  \\ 

   \texttt{ E } & 330  \\ 

   \texttt{ F } & 349  \\ 

   \texttt{ F\# } & 370  \\ 

   \texttt{ G } & 392  \\ 

   \texttt{ G\# } & 415  \\ 

   \texttt{ A440 } & 440 \\ 

   \texttt{ A\# } & 466 \\ 

   \texttt{ B } & 494 \\ 

  OCR0A value for C4=262 Hz
    n+1 = 16MHz / (256 * 2 * T(freq) )
    n+1 = 16000000 / (512 * 262)
    n $<$$>$ 118 

\emph{ Make a Tone of frequency n using CTC toggle mode on Timer0 }
  --------
  .include ``m328Pdef.inc''
    ; connect piezo to Arduino digital pin 6
    ; look at pinout of atmega328 to see output pin of timer0, Channel A
    .def zero = r2
    .def temp = r18 
    .def freq = r16 

  .dseg
  .cseg
  .org 0x0
    rjmp main 
  ; This procedure just sets up timer0 to toggle pinD.6 at the given
  ; frequency. It currently doesnt try to calculate the prescaler value,
  ; just the OC0A compare/match value. Frequency is in ``freq'' (r16)
  ; freq is less than 255 Hz (a limitation!)
  ;  n+1 = 16000000 / (512 * Freq(Tone))
  tone:
    ldi temp, 31250   ; 16000000/512
    ; now divide temp by Frequency (16bit/8bit) or (16bit/16bit)
    ret
  main:
    clr zero               ; set register := 0 and dont change it!
    ldi temp, high(ramend) ; set up the stack
    out SPH, temp 
    ldi temp, low(ramend)
    out SPL, temp 
    sbi DDRD, 6         ; make portD.6 output (arduino pin6)
  begin:
    ldi temp, 118       ; gives Tone C4 (262 Hz) square wave on 16Mhz chip 
                        ; with /64 prescalar 
    out OCR0A, temp     ; load compare value (128)
    ; wgm01:00=0b10 (``ctc'' mode), CS02:00=0b100 (clock/256 prescaler)
    ldi temp, 1$<$$<$COM0A0 | 1$<$$<$WGM01  ; enable Timer0 output pin toggle 
                                    ; and clear-timer-on-compare mode ``ctc''
    out TCCR0A, temp
    ; no interrupts needed.
    ldi temp, 1$<$$<$CS02       ; prescalar = 256
    out TCCR0B, temp   ; loading the clock starts the timer

  here:
    ; micro can do other work here. Its not tied up!
    rjmp here
   ,,,

\section{Piezo Buzzers}

  This is a small device for playing sound. Apparently it can 
  also operate as a sensor. It should be possible to make audible
  tones on piezo with all atmega328 timers (0,1,2). We can 
  drive these audible tones with the output toggle of ``ctc'' mode 
  of the timers.

  A piezo can be connected with either polarity.

  The piezo buzzer can make tunes by simply toggling the output
  on a pin at a certain frequency. We can also achieve this using 
  ctc mode (clear timer on compare) in ``toggle'' mode, or also using
  an interrupt to toggle the output. Using an interrupt has the advantage
  of being able to use any output pin, but if we use the toggle mode in 
  pwm or ctc then we must use the assigned output pins for that particular
  timer.
  
  The automatic toggle is more succinct from a code perspective.

  We could also use PWM (either ``fast'' or ``normal'') ``pulse width modulation''
  mode with a 50\% duty cycle, but I cant think of any advantage over CTC
  mode.
  
  We can use any of the 3 atmega328 timers to drive a piezo speaker. Each
  timer can drive 2 output pins, but since the frequency on both outputs
  for a given timer must be the same, I cannot see the utility of this for 
  making a tone on a piezo.

  
  circuit: pin13-$>$100R(??)--$>$piezo--$>$Ground

  We can change the tone by changing the initial values loaded
  into r17 and r18

\emph{ Buzz a piezo connected to arduino pin 13 then to ground }
  \begin{lstlisting}
   .include "m328Pdef.inc"

  ldi r19,0b00100000
  out DDRB,r19
 again:
  ldi r19,0b00100000
  out PortB,r19
  clr r16
  clr r17
  ldi r17, 20
  ldi r18, 1 
  here:
    dec r16 
    brne here 
    dec r17
    brne here 
    dec r18
    brne here 
  ldi r19,0b00000000
  out PortB,r19
  ldi r18, 1 
  ldi r17, 20
  far:
    dec r16 
    brne far 
    dec r17
    brne far 
    dec r18
    brne far 

  rjmp again
  \end{lstlisting}

\subsection{Piezo Speakers With Timers}

  It does not seem useful to use PWM mode with timer0 or timer2 because 
  it is not possible to change both the frequency and the duty cycle at
  the same time??

  Using an atmega328 MCU running at 16Mhz, then the minimum frequency
  for a square wave using CTC mode is about 30Hz. The frequency
  calculation is given by the usual formula i.e.
\begin{lstlisting}
  formula: freq = Fosc / (2*N*top)
\end{lstlisting}
  Some people give the formula as
\begin{lstlisting}
  formula: freq = Fosc / (2*N*(top+1)
\end{lstlisting}
  where N is prescaler value, and top is the compare match value for the 
  timer
  
  Checking with a piezo buzzer and a tuner app, the second formula seems
  more accurate.

  In general, it is best to use the minimum prescalar value, for a 
  given frequency, because this will allow a more accurate approximation
  for the audible tone. When using the internal clock a variation of 1-2\%
  is normal.

  Note that timer2 has more prescaler values, which would allow better
  approximations for some tones (eg: use prescale 128 for A440).

  So, to obtain A440 (440hz) on a 16Mhz atmega328 (arduino) we use the formula
\begin{lstlisting}
  440hz = 16Mhz / (2*256*top)
\end{lstlisting}
\begin{lstlisting}
  top = 16000000 / (2*256*440) = 71
\end{lstlisting}
  or use
\begin{lstlisting}
  440hz = 16Mhz / (2*256*(top+1))
\end{lstlisting}

  So, the value 71 would be loaded into the OCR0A 
  But if we try to use a prescalar of 64 we get
\begin{lstlisting}
  top = 16000000 / (2*64*440) = 284
\end{lstlisting}
  and 284 is too big to fit into an 8 bit register (OCR0A). This means that 
  256 is the minimum prescalar which can achieve a frequency of 440 herz on
  an 8 bit timer.

  See the example in the section ``toggle in ctc mode for timer0''
  
  Check this frequency with a guitar tuner

\emph{ Timer0 CTC mode output toggle with 440Hz wave on 16Mhz chip  }
  --------
  .include ``m328Pdef.inc''
    ; connect LED/piezo to Arduino digital pin 6
    ; look at pinout of atmega328 to see output pin of timer0 
    .def temp = r18 

  ; Testing:
  ; Using fine tuner" iphone app,
  ;   OCR0A = 71 gives tone freq 434hz
  ;   OCR0A = 70 gives tone freq 440hz

  ; freq = Fosc/(2*N*(top+1))
  ; top+1= 16000000/(2*256*440)
  ; top+1= 71.02 
  ; top = 70 (integer)

  .dseg
  .cseg
  .org 0x0
    rjmp onreset 
  onreset:
    ; assume stack pointer is auto initialised
    sbi DDRD, 6            ; make portD.6 output (arduino pin6)
  begin:
    ldi temp, 70          ; gives approx Tone A440 (440 Hz) square wave on 16Mhz chip 
                          ; with /256 prescalar. 
    out OCR0A, temp       ; load compare value 
    ; WGM bits - waveform generation mode bits, select CTC mode
    ldi temp, 1$<$$<$COM0A0 | 1$<$$<$WGM01  ; enable Timer0 output pin toggle 
                                    ; and clear-timer-on-compare mode ``ctc''
    out TCCR0A, temp
    ; no interrupts needed.
    ; bit names for portability and readability
    ; CS02:00=0b100 (clock/256 prescaler)
    ldi temp, 1$<$$<$CS02  ; prescalar = 256  Clock Select bits
    out TCCR0B, temp   ; loading the clock starts the timer
                       ; stop the timer by loading 0 into CS bits 
  here:
    ; micro can do other work here.
    rjmp here

   ,,,
   
\emph{ Play 3 notes with timer0  }
  --------
  .include ``m328Pdef.inc''
    ; connect piezo speaker to Arduino digital pin 6
    ; and other pin to ground through 100R resistor
    .def temp = r18 

 
  ; Testing:
  ; Using fine tuner" iphone app, prescalar 256
  ;   OCR0A = 71 gives tone freq 434hz
  ;   OCR0A = 70 gives tone freq 440hz
  ;   OCR0A = 59 gives tone freq 521hz (error 2hz)
  ;   OCR0A = 60 gives tone freq 512hz 
  ; freq = Fosc/(2*N*(top+1))
  ; By this testing we can see that once OCR0A is below 60 the errors 
  ; become large (about 8hz). Timer2 maybe a better option here, because 
  ; of more prescale values (eg 128)

  .dseg
  .cseg
  .org 0x0
    rjmp start
  start:
    ; assume stack pointer is auto initialised
    sbi DDRD, 6            ; make portD.6 output (arduino pin6)
  begin:
    ; WGM bits - waveform generation mode bits, select CTC mode
    ldi temp, 1$<$$<$COM0A0 | 1$<$$<$WGM01  ; enable Timer0 output pin toggle 
                                    ; and clear-timer-on-compare mode ``ctc''
    out TCCR0A, temp
    ; no interrupts needed.
    ldi temp, 1$<$$<$CS02  ; prescalar = 256  Clock Select bits
    out TCCR0B, temp   ; loading the clock starts the timer
                       ; stop the timer by loading 0 into CS bits 
  main:
    ldi temp, 70      ; gives approx Tone A440 (440 Hz) square wave on 16Mhz chip 
                      ; with /256 prescalar. 
    out OCR0A, temp   ; load compare value 
    rcall sleep500
    ; play note B4 (approx 494hz) duration 1/2 second
    ; top = 16000000/(2*256*494) - 1 = int(62.256) = 62
    ldi temp, 62   
    out OCR0A, temp       ; load compare value 
    rcall sleep500
    ; for note C4 we could use a prescalar of 64 and top=238
    ; play note C4 (approx 523hz) 
    ; top = 16000000/(2*256*523) - 1 = int(58.751) = 59
    ldi temp, 59   
    out OCR0A, temp       ; load compare value 
    rcall sleep500
    ;rjmp main

  here:
    ; micro can do other work here.
    rjmp here

  ; sleeps for approximately 500 milliseconds on a 16Mhz atmega328
  sleep500:
    clr r16           ; set reg16 := 0
    clr r17
    ldi r18, 40 
    again:            ; a delay loop 40*256\^{}2 instructions
      dec r16         ; 
      brne again 
      dec r17
      brne again 
      dec r18
      brne again 
    ret

   ,,,
   

\subsection{Piezos In C Language}

  These may be modified Gunter Spanner examples

  pin10 -$>$ piezo -$>$ gnd  (no resistor, polarity unimportant)

\emph{ Just stop the piezo !! its so tinny  }
  \begin{lstlisting}
    const int speaker = 10;
    void setup() {
      pinMode(speaker, OUTPUT);
    }
    void loop() {
    }
  \end{lstlisting}
  
\emph{ A simple alarm }
  \begin{lstlisting}
    const int speaker = 10;
    void setup() {
      pinMode(speaker, OUTPUT);
    }
    void loop() {
      tone(speaker, 550, 450);
      delay(1000);
    }
  \end{lstlisting}
  
\emph{ Science fiction sound  }
  \begin{lstlisting}
    const int speaker = 10;
    void setup() {
      pinMode(speaker, OUTPUT);
    }
    void loop() {
      for (int i = 200; i < 500; i += 10) {
        tone(speaker, i, 50);
        delay(20);
      }
      delay(1000);
    }
  \end{lstlisting}
  

\emph{ Sin wav  }
  \begin{lstlisting}
    const int speaker = 9;

    const byte value[] = {
     127,130,133,136,139,143,146,149,152,155,158,161,164,167,170,173,
     176,178,181,184,187,190,192,195,198,200,203,205,208,210,212,215,217,219,221,223,225,227,229,231,233,234,236,238,239,240,
      242,243,244,245,247,248,249,249,250,251,252,252,253,253,253,254,254,254,254,254,254,254,253,253,253,252,252,251,250,249,249,248,247,245,244,243,242,240,239,238,236,234,233,231,229,227,225,223,
       221,219,217,215,212,210,208,205,203,200,198,195,192,190,187,184,181,178,176,173,170,167,164,161,158,155,152,149,146,143,139,136,133,130,127,124,121,118,115,111,108,105,102,99,96,93,90,87,84,81,78,
        76,73,70,67,64,62,59,56,54,51,49,46,44,42,39,37,35,33,31,29,27,25,23,21,20,18,16,15,14,12,11,10,9,7,6,5,5,4,3,2,2,1,1,1,0,0,0,0,0,0,0,1,1,1,2,2,3,4,5,5,6,7,9,10,11,12,14,15,16,18,20,21,23,25,27,29,31,
         33,35,37,39,42,44,46,49,51,54,56,59,62,64,67,70,73,76,78,81,84,87,90,93,96,99,102,105,108,111,115,118,121,124
    };

    void setup() {
      pinMode(speaker, OUTPUT);
      //tone(speaker, 550, 200);
      TCCR1A = 0b10000001;
      TCCR1B = 0b00001001;
    }

    void analogOut(byte val) {
      OCR1A = (val);
    }

    void loop() {
      for (unsigned int j = 0; j < 256; j++) {
        analogOut(value[j]);
        delayMicroseconds(10);
      }
    }

  \end{lstlisting}
  

\section{Power}

  Batteries are rated by their mAh which means ``milliamp hours''
  so an  AA battery rated at 1000mAh could in theory produce
  1 milli-amp for 1000 hours. If a project is powered by battery
  or solar panel, then its really a good idea to reduce power
  consumption. The arduino pro mini is good because it is lower
  power consumption than other arduinos.

  Arduino Uno draws 42mA. So would exhaust 1 AA battery in about
  30 hours

  https://www.openhomeautomation.net/arduino-battery/ 
    an excelent tutorial for powering an atmega328 on a 
    breadboard with only 2 AA batteries and no voltage regulator.
    The atmega is powered at 3V with an external crystal.
    Also discusses ways to make the atmega328 use less power

    
  http://arduino.cc/en/main/standalone
    How to put the arduino on a bread-board powered with a $\sim$9volt
    battery and using a 7805 voltage regulator to reduce voltage
    to 5V. Apparently this type of regulator wastes energy

  http://arduino.cc/en/Tutorial/ArduinoToBreadboard
    similar to above but without incircuit programming of the 
    atmega chip.

  https://alanbmitchell.wordpress.com/2011/10/02/operate-arduino-for-year-from-batteries/
    another low power article

\subsection{Low Power}

  The atmega328 has 5 modes to reduce power consumption which
  can be activated through code.

  Ideas to reduce power consumption, 
    use the on-chip oscillator and clock at 8Megahz. 
    Use a 'switching' voltage regulator.
    run chip at 3V or 3.3V
    turn off unused stuff, like ADC etc

\subsection{Clock}

   you can throttle the internal clock of the ATmega328 on the fly.
   see CLKPR. You can educe the internal 8MHz clock to 31.250kHz 
   with two lines of code. 

\subsection{Sleep Modes}

  http://www.engblaze.com/hush-little-microprocessor-avr-and-arduino-sleep-mode-basics/
    a tutorial about avr sleep modes.

\subsection{Battery Power}

  CR2032 20mm coin cell battery
    runs at 3V and doesnt require a voltage regulator. but only has
    a rating of 200mAh so low power consumption is necessary.

  LR123 type lithium cell.
    high amp hours rating

\subsection{Solar Power}

  Powering an arduino or atmega with solar seems feasible 
  put panels in series to increase voltage, and in parallel
  to increase amperage.

  http://www.instructables.com/id/Solar-powered-arduino-on-the-back-of-a-playing-car/
     This is a very interesting blog on how to create a playing card
     sized solar panel to power an arduino

\section{Car Robot By Bob Elliott}

  The car robot is small, inexpensive and easy to modify. It uses 
  an arduino pro mini, with a voltage regulator, hbridge and 
  hc05 for bluetooth serial communication.

  On android, we are using blueterm 2 to drive the robot. First 
  pair the robot in bluetooth settings (single slow flashing led on 
  the hc05) and then connect in the blueterm screen (double slow flashing
  when successful)

\section{Devices Or Bits And Bobs}

  This section contains a list of handy stuff that can be used in arduino
  projects, with a short description of what the item does

  esp32
    A complete board with wifi and bluetooth. more powerful than the 
    atmega328
  hc-05
    connect to an arduino via bluetooth serial
  ws2811 12mm DC5V leds.
    Big individually addressable strips of leds, use fastled.io library
  cr2032 coin cell battery
    small battery with about 200mAH capacity

\section{Documenting}

\subsection{Fritzing}

  Fritzing is really great. It allows you to create great and pretty
  pictures of things you make, so that you will be able to make them
  again (when you unmake them and forget what you did).

  
\section{Project Ideas}

  This is just a list of things that may be possible with an arduino

   analog meters using old voltage meters hsmag.cc/JBGDAz
   plant waterer hsmag.cc/HhpgXb 
   Synthesizer using lookup tables for sin waves and connecting
    to speaker jack via aligator clips
   boldport pcb solder club

\section{Assemblers For Avr Mcus}

  ``avra'' is available on mac linux and windows, but the 
  mac versions available with brew install seems to have 
  various bugs and quirks. For example, you cant have a label
  and code on the same line! also, you need .org 0x100 in 
  the data segment. It may be possible to fix this by compiling
  the code.

  gavrasm - is a compiler written in pascal which seems to be 
    actively maintained (as of Feb 2020).
  avr-gcc - also contains a 

\section{Avra}

  avra is an assembler for use with avr chips. This is good if
  you dont like c or java.

\emph{ To use register names you need an 'inc' file for the chip }
\begin{lstlisting}
  eg: /usr/share/avra/tn13def.inc
\end{lstlisting}

  avra doesnt seem to come with an inc file for the 
  atmega328 but one should be findable

\emph{ Compile a file to a hex file }
\begin{lstlisting}
  avra hello.asm
\end{lstlisting}

\subsection{Macros}

\emph{ A macro which shows a message if no parameters  }
  -----

  .macro load
  .message ``no parameters specified''
  .endm
  .macro  load\_16\_i
    ldi @0,high(@2)
    ldi @1,low(@2)
  .endm
  ,,,,

\section{C Language Programming}

  Arduino uses a version of c++ for programming (or assembly language, as seen
  above). However, arduino c programs do not have a main() function and cannot
  access many functions from the c standard library (such as file functions)
  for reasons that should, by now, be pretty obvious (ok, I tell you, there is
  no operating system!!!). 
  
  This section will experiment with some c language
  constructs, such as arrays, function pointers, splitting strings etc.
  I will be investigating implementing a system drawing ideas from forth,
  namely, having a dictionary (an array of structures) of commands, with
  the command name and function pointer. Also, a simple data stack
  (implemented as an array).

  The ``setup()'' and ``loop()'' functions seem to be required in arduino
  c.

\emph{ Basic sketch with serial  }
  \begin{lstlisting}
   void setup() {
     Serial.begin(9600);  
     Serial.println("Hello !!!"); 
   }
   void loop() {
   }
  \end{lstlisting}
                    
\subsection{Structures In C}

\emph{ Define a structure and initialize an array of them. }
  ----
    struct song
    $\{$
      char title[100];
      char singer[100];
    $\}$ songlist[] = $\{$
      $\{$``one too many mornings'', ``dylan''$\}$,
      $\{$``money for nothing'', ``knoffler''$\}$,
      $\{$``somewhere'', ``anonymous''$\}$
    $\}$;
    void setup() $\{$ 
      Serial.begin(9600);  
      for (int ii = 0; ii $<$ 3; ii++) $\{$
        Serial.print(``Title:''); Serial.println(songlist[ii].title); 
      $\}$
    $\}$
    void loop() $\{$ $\}$
  ,,,,

\emph{ Define an array and structure array  }
  ----
    long stack[100] = $\{$1,2,3$\}$;
    struct command 
    $\{$
      char name[32];
      char action[100];
    $\}$ dict[] = $\{$
      $\{$``help'', ``...''$\}$,
      $\{$``longBlink'', ``...''$\}$,
      $\{$``shortBlink'', ``...''$\}$
    $\}$;
    void setup() $\{$
    $\}$
    void loop() $\{$ $\}$
  ,,,,

  the F() macro stores strings in flash not RAM which is good
  because there is 32K flash

\emph{ Storing an array of structures flash mem and reading them }
  --------

    struct myStruct                // this is the typedef
    $\{$
    char label[20];
    uint16\_t data;
    $\}$;

    const myStruct myArrayPROGMEM[] PROGMEM = $\{$
      $\{$ ``String1'', 0xCFFF$\}$, 
      $\{$ ``String2'', 0xFC12$\}$,
    $\}$;

    myStruct myArraySRAM;

    void setup() $\{$
      Serial.begin( 9600);
      Serial.println(F( ``Started''));
      for( int i=0; i$<$(sizeof(myArrayPROGMEM)/sizeof(myStruct)); i++) $\{$
         memcpy\_P( \&myArraySRAM, \&myArrayPROGMEM[i], sizeof( myStruct));
         Serial.println( myArraySRAM.label);
         Serial.println( myArraySRAM.data, HEX);
      $\}$
    $\}$

    void loop() $\{$ $\}$

     ,,,,,


\emph{ Put an array of structs into Flash. }
\begin{lstlisting}
  https://forum.arduino.cc/t/storing-a-struct-array-in-progmem/512308/2
\end{lstlisting}

\emph{ Putting an array of strings in flash, and reading it }
  \begin{lstlisting}
    const char string1[] PROGMEM = "String First";
    const char string2[] PROGMEM = "String Second";
    // Then set up a table to refer to your strings.
    const char *const table[] PROGMEM = {string1, string2};
    char buffer[30];  

    void setup() {
      Serial.begin(9600);
      while (!Serial);  
      Serial.println("OK");
    }

    void loop() {
      for (int i = 0; i < 2; i++) {
        // special strcpy function (Flash->RAM)
        strcpy_P(buffer, (char *)pgm_read_word(&(table[i])));  
        // Necessary casts and dereferencing, just copy.
        Serial.println(buffer);
        delay(500);
      }
    }

  ,,,,

  * split serial input into words
  --------
  #define INPUT_SIZE 30
  // Get next command from Serial (add 1 for final 0)
  char input[INPUT_SIZE + 1];

  void setup(){
    Serial.begin(9600);
    Serial.setTimeout(1000);
    Serial.println("Enter words:");
  }

  void loop() {
    if (Serial.available() > 0) {
      byte size = Serial.readBytes(input, INPUT_SIZE);
      if (input[strlen(input)-1] == '\r') {
        input[strlen(input)-1] = 0;
      }

      // Add the final 0 to end the C string
      input[size] = 0;
      // Read each word
      char* command = strtok(input, " ");
      while (command != 0) {
        Serial.print("["); Serial.print(command); Serial.println("]");
        // Find the next command in input string
        command = strtok(0, " ");
      }
    }
  }
    ,,,,

  The system below already seems useful and friendly. The 
  user can connect with a serial connection and find out the
  capabilities of the little arduino machine. We can make 
  this even better by using a bluetooth HC05 module in serial mode
  to connect wirelessly. Then organise a battery power source,
  and the little machine become and independant talking sensor.

  The dictionary is stored in flash.

   using the F() macro to put print strings into flash and
   thus save SRAM memory. Also, we can put the whole dictionary
   into flash. See the link above for how to code it.

  * a forth-ish system in c 
  ----
    #define MAXSTACKLENGTH 20
    #define MAXDICTLENGTH 2 
    #define DICTSIZE 15

    // maybe make the dictionary into an object just like the stack?

    int led = 13;     // on-board LED
    int index = 0;    // index into dictionary
    long value = 0;   // signed long integer to push on stack
    char input[50];   // user input

    // Make a simple stack implementation here.
    // convert code below to use the stack structure.

    typedef struct stacktype 
    {
      long data[MAXSTACKLENGTH];
      int top;
    } Stack;

    enum Wordlist { HELP, STACK, TIME, TEST, FEEDBACK, SOUND};
    typedef struct command 
    {
      char name[32];
      char help[100];
      Wordlist vocab;
      void (*action)(const struct command [], Stack *);
    } Command;
    
    Stack datastack = {{0,0},0};
    struct command cc;

    int size(Stack * ss) { return ss->top; }
    int isEmpty(Stack * ss) { return size(ss) <= 0; }
    int isFull(Stack * ss) { return size(ss) >= MAXSTACKLENGTH-1; }
    void push(Stack * ss, long ll) {
      if (isFull(ss)) { Serial.println(F("Stack Full!")); return; }
      ss->data[ss->top] = ll; ss->top++; 
    }
    long pop(Stack * ss) {
      if (isEmpty(ss)) { Serial.println(F("Stack Empty!")); return 0; }
      ss->top--; return ss->data[ss->top];
    }
    void clear(Stack * ss) {
      if (isEmpty(ss)) { return; } ss->top = 0; 
    }
    void drop(Stack * ss) {
      if (isEmpty(ss)) { return; } ss->top--; 
    }
    void dup(Stack * ss) {
      if (isEmpty(ss)) { return; }
      if (isFull(ss)) { Serial.println(F("Stack Full!")); return; }
      ss->data[ss->top] = ss->data[ss->top - 1]; ss->top++; 
    }
    void swap(Stack * ss) {
      if (size(ss) < 2) { return; }
      long ll = pop(ss); long mm = pop(ss);
      push(ss, ll); push(ss, mm); 
    }
    void plus(Stack * ss) {
      if (size(ss) < 2) { return; }
      long ll = pop(ss); long mm = pop(ss);
      push(ss, ll+mm); 
    }

    int findWord (const Command dd[], char * aword);

    void (*fp)(const Command [], Stack * ss);
    /*
    void listWords (const Command dd[], Stack * ss);
    void greeting (const Command dd[], Stack * ss);
    void help (const Command dd[], Stack * ss);
    void showStack (const Command dd[], Stack * ss);
    void printItem (const Command dd[], Stack * ss);
    void clearStack (const Command dd[], Stack * ss);
    void drop (const Command dd[], Stack * ss);
    void dup (const Command dd[], Stack * ss);
    void swap (const Command dd[], Stack * ss);
    void plus (const Command dd[], Stack * ss);
    void millis (const Command dd[], Stack * ss);
    void star(const Command dd[], Stack * ss);
    void blink(const Command dd[], Stack * ss);
    void blinkNum(const Command dd[], Stack * ss);
    void printUpTime(const Command dd[], Stack * ss);
    */

    // do we really need this? A flat array seems to be sufficient
    typedef struct dictionary 
    {
      struct command contents[MAXDICTLENGTH];
      int size;
    } Dict; 

    void greeting (const Command dd[], Stack * ss) {
      Serial.println(F("Hello, how are you?!")); 
      Serial.println(
        F("This is a 'forth-like' system with a data stack running on arduino.")); 
      Serial.println(F("Type 'words' to see all commands")); 
      Serial.println(F("Type 'help' for a description of all commands. ")); 
      Serial.println(F("Enter a number to push it onto the stack.")); 
    }

    // returns -1 if word not found, otherwise the index.
    int findWord (const Command dd[], char * aword) {
      struct command cc;
      //int dictsize = sizeof(dd)/sizeof(struct command);
      for (int ii = 0; ii < DICTSIZE; ii++) {
        //memcpy_P( &myArraySRAM, &myArrayPROGMEM[i], sizeof(acommand));
        memcpy_P( &cc, &dd[ii], sizeof(cc));
        if (strcmp(cc.name, aword) == 0 ) { return ii; }  
      }
      return -1;
    }

    void help (const Command dd[], Stack * ss) {
      struct command cc;
      Serial.println(F("Ok relax, help is coming:")); 
      for (int ii = 0; ii < DICTSIZE; ii++) {
        memcpy_P( &cc, &dd[ii], sizeof(cc));
        Serial.print("  ["); Serial.print(cc.name);
        Serial.print("] "); Serial.println(cc.help);
      }
    }

    void showStack (const Command dd[], Stack * ss) {
      Serial.print(F("Stack [")); 
      for (int ii = 0; ii < size(ss); ii++) {
        Serial.print(ss->data[ii]);
        Serial.print(" ");
      } 
      Serial.print(F("]")); 
    }

    void printItem (const Command dd[], Stack * ss) {
      if (isEmpty(ss)) { return; }
      Serial.println(pop(ss));
    }

    // duplicated to conform to the function pointer signature.
    void clearStack(const Command dd[], Stack * ss) { clear(ss); }
    void drop(const Command dd[], Stack * ss) { drop(ss); }
    void dup(const Command dd[], Stack * ss) { dup(ss); }
    void swap(const Command dd[], Stack * ss) { swap(ss); }
    void plus(const Command dd[], Stack * ss) { plus(ss); }

    void millis(const Command dd[], Stack * ss) { push(ss, millis()); }

    void star (const Command dd[], Stack * ss) {
      if (size(ss) < 1) {
        Serial.println(F("star needs one stack value")); return;
      }
      int value = pop(ss);
      for (int ii = 0; ii < value; ii++) { Serial.print("*"); }
      Serial.println();
    }

    void blink(long duration, long times) {
      for (int ii = 0; ii < times; ii++) {
        digitalWrite(led, HIGH);   
        delay(duration);               
        digitalWrite(led, LOW);  
        delay(duration);           
      }
    }

    void blinkNum(const Command dd[], Stack * ss) {
      if (size(ss) < 1) {
        Serial.println(F("blinknum needs 1 stack value")); return;
      }
      long value = pop(ss);
      int tens = (value/10)%100;
      int ones = value % 10;
      blink(500, tens); blink(200, ones);
      delay(2000);               
      blink(500, tens); blink(200, ones);
    }

    void blink(const Command dd[], Stack * ss) {
      if (size(ss) < 2) {
        Serial.println(F("blink needs 2 stack values")); return;
      }
      int times = pop(ss);
      int duration = pop(ss);
      Serial.print(F("Blinking led (")); Serial.print(led);
      Serial.print(F(") ")); Serial.print(times);
      Serial.print(F(" times with duration ")); Serial.print(duration);
      Serial.println(F(" milliseconds.")); 
      for (int ii= 0; ii < times; ii++) {
        digitalWrite(led, HIGH);   
        delay(duration);               
        digitalWrite(led, LOW);  
        delay(duration);           
      }
    }

    void printUpTime(const Command dd[], Stack * ss) {
      unsigned long currentMillis = millis();
      unsigned long seconds = currentMillis / 1000;
      unsigned long minutes = seconds / 60;
      unsigned long hours = minutes / 60;
      unsigned long days = hours / 24;
      currentMillis %= 1000;
      seconds %= 60;
      minutes %= 60;
      hours %= 24;
      Serial.print(F("Run-time: ")); 
      if (hours < 10) { Serial.print(F("0")); }
      Serial.print(hours); Serial.print(F(":"));
      if (minutes < 10) { Serial.print(F("0")); }
      Serial.print(minutes); Serial.print(F(":"));
      if (seconds < 10) { Serial.print(F("0")); }
      Serial.print(seconds);
      Serial.println(F(" (h:m:s)")); 
    }

    void listWords (const Command dd[], Stack * ss) {
      /* dd is actually pointer to first struct */
      struct command cc;
      Serial.println("All commands:"); 
      for (int ii = 0; ii < DICTSIZE; ii++) {
        memcpy_P( &cc, &dd[ii], sizeof(cc));
        Serial.print(" "); Serial.print(cc.name); 
      }
      Serial.println(" "); 
    }

    const Command dict[] PROGMEM = {
      {"hi", "gives a greeting", HELP, greeting},
      {"help", "show all words and help", HELP, help},
      {"words", "just show words", HELP, listWords},
      {".s", "show the stack", STACK, showStack},
      {".", "print and drop top stack item", STACK, printItem},
      {"clear", "clear the stack", STACK, clearStack},
      {"drop", "drop top stack item", STACK, drop},
      {"dup", "duplicate top stack item", STACK, dup},
      {"swap", "swap top 2 stack items", STACK, swap},
      {"+", "add top 2 stack items", STACK, plus},
      {"ms", "push milliseconds run-time", TIME, millis},
      {".time", "print current run-time in minutes+seconds", 
         TIME, printUpTime},
      {"star", "print n stars", TEST, star},
      {"blinknum", "blink number 1-99 on led (tens slow blinks)", 
         FEEDBACK, blinkNum},
      {"blink", "(dur repeat --) blinks led on pin 13 'n' times duration d ms",         FEEDBACK,  blink}
    };

    void setup() {
      pinMode(led, OUTPUT);     
      Serial.setTimeout(60000);  
      Serial.begin(9600);  
      while (!Serial);  // wait for serial port. Needed for native USB
      Serial.println("OK"); Serial.println("Talking to Ardy..."); 
    }

    void loop() {
      char * end;       
      showStack(dict, &datastack);
      Serial.print("#>");
      while (Serial.available() == 0) { }
      // but it depends on serial monitor settings what is your
      // line ending. It could be \n etc
      // this blocks until \r received or timeout.
      Serial.readStringUntil('\r').toCharArray(input, 20);
      // remove \r char at end of string
      if (input[strlen(input)-1] == '\r') {
        input[strlen(input)-1] = 0;
      }
      //Serial.print("Got: ["); Serial.print(input); Serial.println("]");
      //help(dict, &datastack);
      
      // Read each word
      char* oneword = strtok(input, " ");
      while (oneword != 0) {
        // Serial.print("["); Serial.print(oneword); Serial.println("]");
        index = findWord(dict, oneword);
        if (index == -1) {
          // 'atol' cant distinguish between 0 and error
          // 10 is the base for the conversion.
          // convert word to long integer
          value = strtol(oneword, &end, 10);
          // but this is pushing zero on empty input
          if (!*end) {
            // word is an integer, so push it. 
            push(&datastack, value);
          } else {
            Serial.print(F("Sorry, what does '"));
            Serial.print(oneword); Serial.print(F("' mean?"));
            Serial.println(" ");
            break;
          }
        } else {
          // the function pointer is in flash (in a command struct)
          // so has to be copied over to sram.
          memcpy_P( &cc, &dict[index], sizeof(cc));
          // execute word as a function pointer
          (*cc.action)(dict, &datastack);
        }
        oneword = strtok(0, " ");
      } // while more words
    } // loop
  ,,,,


VIM AND AVR PROGRAMMING

  Vim can be used to compile, and upload to the arduino board
  code in a text file, or even code contained within another
  type of text document. Also, how to compile arduino c...? from 
  the command line.

  Since I like to write notes to myself when I am learning about the 
  avr chips (and other topics) I like to put code snippets inside of 
  a document (such as this booklet). Having done that, I like to check
  that the code snippets actually work. Using vim, avra, avrdude, and 
  picocom, this can be done with very few keystrokes (eg ",a" or ",u")

  * a mac osx style usb serial port
  >> /dev/tty.usbserial-A8008Ghy

  * map the key sequence ';av' to compile the whole file with avra
  >> map ;as :!avra %<cr>
  or >> map ;as :!avra % -o %:r.hex<cr>
 
  The second example is not necessary since by default avra
  creates a file called name.hex where the source file is 'name.asm'

  In the examples below, the complete assembly or c program is 
  supposed to be within 2 'markers' within a document. The markers
  are '---' on a line by itself and ',,,' on a line by itself. These
  2 markers mark the beginning and end of the assembly program
  within the document. Also the cursor needs to be between 
  these 2 markers.

  * extract and compile arduino c code and upload to 'uno' board
  >> map ,C :?^ *---?+1,/,,,/-1w ! ( cat - ) > sketch/test/test.ino; cd sketch/test; make; cd build-uno; sudo avrdude -p atmega328p -carduino -P/dev/ttyACM0 -b115200 -D -Uflash:w:test.hex:i

  * compile an avr assembly program within a document to 'test.hex'
  >> map ,a :?^ *---?+1,/,,,/-1w ! ( cat - ) > test.asm; avra test.asm; 

  * compile assembler source and upload to the arduino 'duemilanove' board
  >> map ,u :?^ *---?+1,/,,,/-1w ! ( cat - ) > test.asm; avra test.asm; sudo avrdude -p atmega328p -carduino -P/dev/ttyUSB0 -b57600 -D -Uflash:w:test.hex:i
 
  * compile asm code and upload to the arduino 'uno' compatible board
  >> map ,v :?^ *---?+1,/,,,/-1w ! ( cat - ) > test.asm; avra test.asm; sudo avrdude -p atmega328p -carduino -P/dev/ttyACM0 -b115200 -D -Uflash:w:test.hex:i

  It will probably be necessary to change the exact /dev/tty.usb* device below

  * compile source and upload to the arduino 'uno' compatible board on mac osx
  >> map ,V :?^ *---?+1,/,,,/-1w ! ( cat - ) > test.asm; avra test.asm; sudo avrdude -p atmega328p -carduino -P/dev/tty.usbmodem14201 -b115200 -D -Uflash:w:test.hex:i

  * open a serial terminal to communicate with an arduino
  >> map ,s :! sudo picocom -b 9600 --echo /dev/ttyACM0

  not working! says filedes is not a tty
  * compile, upload and open a serial terminal to test on duemilenove with linux
  >> map ,x :?^ *---?+1,/,,,/-1w ! ( cat - ) > test.asm; avra test.asm; sudo avrdude -p atmega328p -carduino -P/dev/ttyUSB0 -b57600 -D -Uflash:w:test.hex:i; sudo picocom -b 9600 --echo /dev/ttyUSB0

  * open a serial terminal for comms with an "uno" board on mac osx
  >> map ,t :! sudo picocom -b 9600 --echo /dev/tty.usbmodem14201

  * and adjust the serial device according to the operating system
  >> map ,S :! sudo picocom -b 9600 --echo /dev/ttyUSB0
  >> map ,S :! sudo picocom -b 9600 --echo /dev/tty.usbserial-A8008Ghy # eg: mac osx
  >> 


  Type control-a control-x to exit picocom

  The following is useful for determining how much space is 
  left within a boot file (which is limited to 512 bytes)

  * see how big a compiled file is without running it 
  >> map ;ab :?^ *---?+1,/,,,/-1w ! ( cat - ) > test.asm; avra test.asm; ls -la
 
VIM WITH ARDUINO C ....

  We use arduino-mk with a Makefile in a subdirectory to automatically
  compile and upload a sketch which is written in arduino c with the "vim"
  text editor. The only tricky bit is automatically getting the arduino
  libraries into the Makefile. We may need to hand edit that file in 
  some cases.

  the arduino-mk needs to be configured, see above in "setup"

  When 'make' is used, it actually puts the hex file in a subfolder
  'build-uno' etc.

  * extract an arduino c prog in a vim doc to a subdirectory "sketch" 
  >> map ;ac :?^ *---?+1,/,,,/-1w ! ( cat - ) > sketch/test/test.ino; ls -la sketch/test

  * compile an arduino c prog in a vim doc to a subdirectory "sketch/test" 
  >> map ;ac :?^ *---?+1,/,,,/-1w ! ( cat - ) > sketch/test/test.ino; cd sketch/test; make 2>&1 \| less

  Redirect stderr to less so that we can see what causes a compile to 
  fail.

  if there are other ".ino" files in sketch/test this will fail

  * compile an arduino c prog and upload to the board 
  >> map ;au :?^ *---?+1,/,,,/-1w ! ( cat - ) > sketch/test/test.ino; cd sketch/test; make; make upload

  This last mapping is not quite working, programmer out of sync etc
  only small problem I think.

  The Makefile in the sketch/test subfolder has a tag that determines 
  the type of arduino board (pro mini 328 3v3 etc) and the serial port.
  Adjust that makefile for different boards

  * look in doc folder for good examples of using arduino-mk
  >> /usr/share/doc/arduino-mk/examples/

  * an example Makefile for arduino-mk bash uploading 
  --------
    #BOARD_TAG=pro328
    BOARD_TAG=uno
    #ARDUINO_PORT = /dev/cu.usb*
    #ARDUINO_PORT = /dev/ttyUSB*
    # try a very general tty port, ttyUSB0, ttyS0
    ARDUINO_PORT = /dev/tty*
    #ARDUINO_LIBS = Ethernet Ethernet/utility SPI
    #ARDUINO_LIBS = Servo 
    include /usr/share/arduino/Arduino.mk
  \end{lstlisting}

   \end{document}
