hello: split out timer; add serial
authorTero Marttila <terom@paivola.fi>
Thu, 03 Apr 2014 19:44:53 +0300
changeset 52 237d1f5c1c32
parent 51 ec6271f0637b
child 53 dfe67409fbcd
hello: split out timer; add serial
src/hello.c
src/serial.c
src/stdlib.h
src/timer.c
--- a/src/hello.c	Thu Apr 03 19:44:13 2014 +0300
+++ b/src/hello.c	Thu Apr 03 19:44:53 2014 +0300
@@ -1,116 +1,34 @@
 #include <avr/io.h>
-#include "stdlib.h"
-
-#include <avr/interrupt.h>
-
-#define TIMER_FLAGS     GPIOR0
-#define TIMER1_BUSY     1
-
-/*
- * Setup timers.
- */
-void timer_init (void)
-{
-    TCCR1A = (
-            // OC1A output pin disconnected
-            0b00 << COM1A0
-            // OC1B output pin disconnected
-        |   0b00 << COM1B0
-            // no PWM
-        |   0b00 << WGM10
-    );
-    TCCR1B = (
-            // CTC mode
-            0b01 << WGM12 
-    );
-    TCCR1C = 0;
-}
-
-void timer1_start (short cycles)
-{
-    // count up from zero...
-    TCNT1 = 0;
-
-    // ...to the given number of timer cycles
-    OCR1A = cycles;
-
-    // start!
-    sbi(&TIMER_FLAGS, TIMER1_BUSY);
-    TIMSK1 = (
-            // OCA interrupt
-            0b1 << OCIE1A       // enable
-    );
-    TCCR1B = (
-            // WGM
-            0b01  << WGM12      // CTC
 
-            // clocksource
-        |   0b101 << CS10       // 1024'th
-    );
-}
-
-static void timer1_stop ()
-{
-    // WGM: normal
-    // clocksource: stop
-    TCCR1B = 0;
-
-    cbi(&TIMER_FLAGS, TIMER1_BUSY);
-}
-
-ISR(TIMER1_COMPA_vect)
-{
-    timer1_stop();
-
-    // XXX: cpu will automatically wake up from sleep()
-}
-
-/*
- * Sleep on timer1 interrupt.
- */
-void timer_sleep (int cycles)
-{
-    // set timer
-    timer1_start(cycles);
-
-    // sleep
-    // TODO: PRR
-    SMCR = (
-            // idle sleep
-            (0b00 << SM0)
-
-            // enable sleep
-        |   (0b1 << SE)
-    );
-    
-    // sleep
-    while (tbi(&TIMER_FLAGS, TIMER1_BUSY)) {
-        __asm__ ( "sleep" :: );
-    }
-
-    // cleanup
-    SMCR = 0;
-}
+#include "stdlib.h"
+#include "timer.c" // XXX
+#include "serial.c" // XXX
 
 int main (void)
 {
     timer_init();
+    serial_init();
 
     // LED
     sbi(&DDRB, DDB5);
+    serial_enable();
 
     sei();
 
     // blink
+    char c = 'X';
     short timeout = 1000;
     short delta = 10;
 
     while (true) {
+        serial_write(c);
+
         // bitflip
         xbi(&PORTB, PORTB5);
         
-        timer_sleep(timeout);
+        //timer_sleep(timeout);
+        //timeout += delta;
         
-        timeout += delta;
+        c = serial_read();
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/serial.c	Thu Apr 03 19:44:53 2014 +0300
@@ -0,0 +1,88 @@
+
+static enum {
+    SERIAL_MODE_ASYNC   = 0b00,
+} serial_mode = SERIAL_MODE_ASYNC;
+
+static enum {
+    SERIAL_BAUD_9600    = 103,
+
+} serial_baud = SERIAL_BAUD_9600;
+
+static enum {
+    SERIAL_PARITY_N     = 0b00,
+
+} serial_parity = SERIAL_PARITY_N;
+
+static enum {
+    SERIAL_STOPBITS_1   = 0b0,
+
+} serial_stopbits = SERIAL_STOPBITS_1;
+
+static enum {
+    SERIAL_CHARS_8      = 0b011,
+} serial_chars = SERIAL_CHARS_8;
+
+/*
+ * Setup the UART for serial mode.
+ */
+void serial_init ()
+{
+    UCSR0A = (
+            // Double the USART Transmission Speed
+            (0b0 << U2X0)   // single speed
+            
+            // Multi-processor Communication Mode
+        |   (0b0 << MPCM0)  // off
+    );
+    UCSR0B = (
+            // Character Size
+            ((serial_chars >> 2) << UCSZ02) // standard character sizes
+    );
+    UCSR0C = (
+            // USART Mode Select
+            (serial_mode << UMSEL00) // async
+
+            // Parity Mode
+        |   (serial_parity << UPM00)
+            
+            // Stop Bit Select
+        |   (serial_stopbits << USBS0)
+
+            // Character Size
+        |   ((serial_chars & 0b11) << UCSZ00)
+        
+            // Clock Polarity
+        |   (0b0 << UCPOL0)
+    );
+    UBRR0 = serial_baud;
+}
+
+void serial_enable ()
+{
+    UCSR0B = (
+            // Receiver Enable
+            (0b1 << RXEN0)  // enabled
+
+            // Transmitter Enable
+        |   (0b1 << TXEN0)  // enabled
+
+            // Character Size
+        |   ((serial_chars >> 2) << UCSZ02) // standard character sizes
+    );
+}
+
+char serial_read ()
+{
+    while (!tbi(&UCSR0A, RXC0))
+        ;
+
+    return UDR0;
+}
+
+void serial_write (char c)
+{
+    while (!tbi(&UCSR0A, UDRE0))
+        ;
+
+    UDR0 = c;
+}
--- a/src/stdlib.h	Thu Apr 03 19:44:13 2014 +0300
+++ b/src/stdlib.h	Thu Apr 03 19:44:53 2014 +0300
@@ -1,5 +1,3 @@
-#include <util/delay.h>
-
 #define false       0
 #define true        1
 
@@ -24,9 +22,3 @@
 {
     *port ^= (1 << bit);
 }
-
-void delay_1s ()
-{
-    // busyloop
-    _delay_ms(1000);
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/timer.c	Thu Apr 03 19:44:53 2014 +0300
@@ -0,0 +1,92 @@
+#include <avr/interrupt.h>
+
+#define TIMER_FLAGS     GPIOR0
+#define TIMER1_BUSY     1
+
+/*
+ * Setup timers.
+ */
+void timer_init (void)
+{
+    TCCR1A = (
+            // OC1A output pin disconnected
+            0b00 << COM1A0
+            // OC1B output pin disconnected
+        |   0b00 << COM1B0
+            // no PWM
+        |   0b00 << WGM10
+    );
+    TCCR1B = (
+            // CTC mode
+            0b01 << WGM12 
+    );
+    TCCR1C = 0;
+}
+
+void timer1_start (short cycles)
+{
+    // count up from zero...
+    TCNT1 = 0;
+
+    // ...to the given number of timer cycles
+    OCR1A = cycles;
+
+    // start!
+    sbi(&TIMER_FLAGS, TIMER1_BUSY);
+    TIMSK1 = (
+            // OCA interrupt
+            0b1 << OCIE1A       // enable
+    );
+    TCCR1B = (
+            // WGM
+            0b01  << WGM12      // CTC
+
+            // clocksource
+        |   0b101 << CS10       // 1024'th
+    );
+}
+
+static void timer1_stop ()
+{
+    // WGM: normal
+    // clocksource: stop
+    TCCR1B = 0;
+
+    cbi(&TIMER_FLAGS, TIMER1_BUSY);
+}
+
+ISR(TIMER1_COMPA_vect)
+{
+    timer1_stop();
+
+    // XXX: cpu will automatically wake up from sleep()
+}
+
+/*
+ * Sleep on timer1 interrupt.
+ */
+void timer_sleep (int cycles)
+{
+    // set timer
+    timer1_start(cycles);
+
+    // sleep
+    // TODO: PRR
+    SMCR = (
+            // idle sleep
+            (0b00 << SM0)
+
+            // enable sleep
+        |   (0b1 << SE)
+    );
+    
+    // sleep
+    while (tbi(&TIMER_FLAGS, TIMER1_BUSY)) {
+        __asm__ ( "sleep" :: );
+    }
+
+    // cleanup
+    SMCR = 0;
+}
+
+