src/hello-dmx.c
changeset 65 625f34328820
parent 62 2d68a76322cb
child 66 0cf14786b909
equal deleted inserted replaced
64:f9221fa50c75 65:625f34328820
     3  *
     3  *
     4  * See doc/dmx.txt for the RX-485 bus protocol details...
     4  * See doc/dmx.txt for the RX-485 bus protocol details...
     5  */
     5  */
     6 
     6 
     7 #include <avr/io.h>
     7 #include <avr/io.h>
     8 #include <util/delay.h>
       
     9 
     8 
    10 #include "stdlib.h"
     9 #include "stdlib.h"
       
    10 #include "timer.c"
       
    11 #include "serial.c"
       
    12 #include "dmx.c"
    11 
    13 
    12 // debug
    14 // debug
    13 #define DEBUG_DDR   DDRB
    15 #define DEBUG_DDR   DDRB
    14 #define DEBUG_PORT  PORTB
    16 #define DEBUG_PORT  PORTB
    15 #define DEBUG_LED   0
    17 #define DEBUG_LED   0
    32 void led_toggle ()
    34 void led_toggle ()
    33 {
    35 {
    34     xbi(&DEBUG_PORT, DEBUG_LED);
    36     xbi(&DEBUG_PORT, DEBUG_LED);
    35 }
    37 }
    36 
    38 
    37 // DMX
    39 // dmx
    38 #define DMX_DDR     DDRB
    40 /*
    39 #define DMX_PORT    PORTB
    41  * DMX state
    40 #define DMX_DATA    3       // SPI MOSI
    42  */
    41 
    43 static struct dmx_state {
    42 // baud rate: 250k = 4µs / bit
    44     byte out[256];
    43 #define DMX_BAUD    (250 * 1000)
    45     byte count;
    44 #define DMX_US      4
    46 } dmx;
    45 
    47 
    46 // CPU cycles / bit: 64 @ 16Mhz
    48 
    47 #define DMX_CYCLES  (F_CPU / DMX_BAUD)
    49 enum state {
    48 
    50     START       = '\n',
    49 void dmx_init ()
    51     CMD         = ';',
    50 {
    52     ARG         = ',',
    51     // dmx data out: idle (high)
    53     ERROR       = '!',
    52     sbi(&DMX_PORT, DMX_DATA);
    54 };
    53     sbi(&DMX_DDR, DMX_DATA);
    55 
    54 }
    56 enum cmd {
    55 
    57     CMD_
    56 static inline void dmx_high ()
    58 };
    57 {
    59 
    58     sbi(&DMX_PORT, DMX_DATA);
    60 #define CONSOLE_ARGS 8
    59 }
    61 
    60 
    62 /*
    61 static inline void dmx_low ()
    63  * Console input state.
    62 {
    64  */
    63     cbi(&DMX_PORT, DMX_DATA);
    65 static struct console {
    64 }
    66     enum state state;
    65 
    67 
    66 #define dmx_pause(bits) _delay_us((DMX_US * bits))
    68     enum cmd cmd;
    67 
    69     char argc;
    68 static void dmx_break ()
    70     char argv[CONSOLE_ARGS];
    69 {
    71 } console;
    70     // break
    72 
    71     dmx_low();
    73 /*
    72     dmx_pause(22);
    74  * Process console command.
    73 
    75  */
    74     // mark-after-break (MAB)
    76 int command ()
    75     dmx_high();
    77 {
    76     dmx_pause(2);
    78     switch (console.cmd) {
    77 }
    79         default:
    78 
    80             return '?';
    79 #include "dmx_frame.c"
    81     }
    80 
    82 }
    81 static void dmx_packet (byte r, byte g, byte b)
    83 
       
    84 /*
       
    85  * Process console input.
       
    86  */
       
    87 char input (char c)
       
    88 {
       
    89     // control
       
    90     if (c == '\r') {
       
    91         char ret = '?';
       
    92 
       
    93         if (console.state == CMD) {
       
    94             console.argc = 0;
       
    95         } else if (console.state == ARG) {
       
    96             console.argc++;
       
    97         } else {
       
    98             console.state = START;
       
    99             return '\n';
       
   100         }
       
   101 
       
   102         // command
       
   103         if ((ret = command(console.cmd))) {
       
   104 
       
   105         } else {
       
   106             ret = '\n';
       
   107         }
       
   108         
       
   109         // return to START with response
       
   110         console.state = START;
       
   111         return ret;
       
   112     
       
   113     } else if (c == ' ' || c == '\t') {
       
   114         // argument
       
   115         if (console.state == CMD) {
       
   116             console.state = ARG;
       
   117             console.argc = 0;
       
   118 
       
   119             return c;
       
   120 
       
   121         } else if (console.state == ARG) {
       
   122             if (console.argc++ < CONSOLE_ARGS) {
       
   123                 console.argv[console.argc] = 0;
       
   124 
       
   125                 return c;
       
   126             }
       
   127         }
       
   128 
       
   129     // printable    
       
   130     } else if (32 < c && c < 128) {
       
   131         // process input char
       
   132         if (console.state == START)  {
       
   133             console.cmd = c;
       
   134             console.state = CMD;
       
   135 
       
   136             return c;
       
   137 
       
   138         } else if (console.state == ARG) {
       
   139             if (c >= '0' && c <= '9') {
       
   140                 console.argv[console.argc] *= 10;
       
   141                 console.argv[console.argc] += (c - '0');
       
   142 
       
   143                 return c;
       
   144             }
       
   145         }
       
   146     } else {
       
   147         // ignore
       
   148         return ' ';
       
   149     }
       
   150         
       
   151     // reject
       
   152     console.state = ERROR;
       
   153     return ERROR;
       
   154 }
       
   155 
       
   156 /*
       
   157  * Tick output state
       
   158  */
       
   159 void update ()
    82 {
   160 {
    83     dmx_break();
   161     dmx_break();
    84     dmx_frame(0);
   162     dmx_frame(0);
    85 
   163 
    86     dmx_frame(0);       // control
   164     for (byte i = 0; i < dmx.count; i++) {
    87     dmx_frame(r);
   165         dmx_frame(dmx.out[i]);
    88     dmx_frame(g);
   166     }
    89     dmx_frame(b);
       
    90     dmx_frame(0);       // madness
       
    91 }
   167 }
    92 
   168 
    93 void main ()
   169 void main ()
    94 {
   170 {
    95     led_init();
   171     led_init();
    96     dmx_init();
   172     timer_init();
    97 
   173     serial_init();
    98     // dmx
   174     //dmx_init();
       
   175 
       
   176     // mainloop
       
   177     char c = '>';
       
   178     unsigned timeout = 8000; // 2Hz
       
   179     
       
   180     sei();
       
   181 
    99     while (true) {
   182     while (true) {
   100         dmx_packet(0x00, 0x00, 0xff);
   183         // sleep
   101         dmx_pause(100);
   184         //led_on();
   102 
   185         if (timer_sleep(timeout)) {
       
   186             c = '.';
       
   187 
       
   188         } else if ((c = serial_read())) {
       
   189             // got serial data
       
   190             c = input(c);
       
   191 
       
   192         } else {
       
   193             // unknown interrupt
       
   194             c = '?';
       
   195         }
       
   196         //led_off();
       
   197         
       
   198         // respond
       
   199         serial_write(c);
       
   200         
       
   201         // output
       
   202         update();
       
   203         
   103         led_toggle();
   204         led_toggle();
   104     }
   205     }
   105 }
   206 }