dmx.s
changeset 89 1b3cea759eff
parent 88 c923295ee520
child 90 13c2deb919d1
equal deleted inserted replaced
88:c923295ee520 89:1b3cea759eff
     1 ;;; vim: set ft=avr:
       
     2 
       
     3 .nolist
       
     4 .include "m168def.inc"      ; Same family as 328P
       
     5 .list
       
     6 
       
     7 .include "macros.inc"
       
     8 
       
     9 ;; Interrupt Vector
       
    10 .cseg
       
    11 .org 0x0000
       
    12         rjmp        Main
       
    13 
       
    14 
       
    15 ;; CPU cycles / second: 16 Mhz
       
    16 .set CPU_CYCLES = 16 * 1000 * 1000
       
    17 
       
    18 ;; Delays
       
    19 .include "delay.inc"
       
    20 
       
    21 ;; DMX baud raite: 250k
       
    22 .set DMX_BAUD = 250 * 1000
       
    23 
       
    24 ;; CPU cycles / bit: 64
       
    25 .set DMX_CYCLES = CPU_CYCLES / DMX_BAUD
       
    26 
       
    27 ;; DMX output I/O
       
    28 .set DMX_DDR = DDRB
       
    29 .set DMX_PORT = PORTB
       
    30 .equ DMX_DATA = PORTB3
       
    31 
       
    32 ;; DMX protocol timer
       
    33 ; Registers
       
    34 .set DMX_TIMER_CRA = TCCR2A
       
    35 .set DMX_TIMER_CRB = TCCR2B
       
    36 .set DMX_TIMER_CNT = TCNT2
       
    37 .set DMX_TIMER_OCRA = OCR2A
       
    38 .set DMX_TIMER_OCRB = OCR2B
       
    39 .set DMX_TIMER_IMSK = TIMSK2
       
    40 .set DMX_TIMER_IFR = TIFR2
       
    41 
       
    42 ; Compare output match isn't used
       
    43 .set DMX_TIMER_COMA = 0b00
       
    44 .set DMX_TIMER_COMB = 0b00
       
    45 
       
    46 ; Control register, generation mode value
       
    47 .set DMX_TIMER_WGM_10 = 0b10        ; CTC
       
    48 .set DMX_TIMER_WGM_2 = 0b0
       
    49 
       
    50 ; Clock select
       
    51 .set DMX_TIMER_CS_STOP = 0b000
       
    52 .set DMX_TIMER_CS = 0b001      ; 1/1
       
    53 ;.set DMX_TIMER_CS = 0b111       ; 1/1024
       
    54 
       
    55 ; Counted value
       
    56 .set DMX_TIMER_TOP = DMX_CYCLES     ; number of cycles for baud
       
    57 
       
    58 ;; Debug LED
       
    59 .set LED_DDR = DDRB
       
    60 .set LED_PORT = PORTB
       
    61 .set LED_PIN = PINB
       
    62 .set LED_BIT = PORTB0
       
    63 
       
    64 ;; Set up DMX output
       
    65 DMX_Init:
       
    66     ; Setup output port
       
    67         ; out
       
    68         sbi     DMX_DDR, DMX_DATA
       
    69 
       
    70         ; drive high
       
    71         sbi     DMX_PORT, DMX_DATA
       
    72 
       
    73     ; Setup timer
       
    74         ; setup CTC mode with no output pins
       
    75         poke        [DMX_TIMER_CRA, r16, (DMX_TIMER_COMA << COM2A0) | (DMX_TIMER_COMB << COM2B0) | (DMX_TIMER_WGM_10 << WGM20)]
       
    76         poke        [DMX_TIMER_CRB, r16, (DMX_TIMER_WGM_2 << WGM22) | (DMX_TIMER_CS_STOP << CS20)]
       
    77 
       
    78         ; trigger threshold for CTC
       
    79         poke        [DMX_TIMER_OCRA, r16, (DMX_TIMER_TOP)]
       
    80 		
       
    81     ; OK
       
    82     ret
       
    83 
       
    84 ;; Start Break signal
       
    85 ;;
       
    86 ;; 22 bits - 1s long; then DMX_Break_Mark
       
    87 ;;
       
    88 DMX_Break_Start:
       
    89     ; Low
       
    90         cbi         DMX_PORT, DMX_DATA
       
    91 
       
    92     ret
       
    93 
       
    94 ;; Start Mark-after-break signal
       
    95 ;;
       
    96 ;; 2 bits - 1s long; then DMX_Break_End
       
    97 ;;
       
    98 DMX_Break_Mark:
       
    99     ; High
       
   100         sbi         DMX_PORT, DMX_DATA
       
   101 
       
   102     ret
       
   103 
       
   104 ;; End break; prepare for DMX_Frame
       
   105 DMX_Frame_Start:
       
   106     ; Start timer
       
   107         poke        [DMX_TIMER_CRB, r20, (DMX_TIMER_WGM_2 << WGM22) | (DMX_TIMER_CS << CS20)]
       
   108     
       
   109     ret
       
   110 
       
   111 ;; Do a full DMX break, using some random length
       
   112 ;;
       
   113 DMX_Break:
       
   114     ; Break
       
   115         ; start
       
   116         rcall       DMX_Break_Start
       
   117 
       
   118         ; wait; about 100ms?
       
   119         ldi         r20, 82 / 10
       
   120         rcall       VarDelay
       
   121 
       
   122     ; MAB
       
   123         ; mark
       
   124         rcall       DMX_Break_Mark
       
   125 
       
   126         ; short wait
       
   127         ldi         r20, 1
       
   128         rcall       VarDelay
       
   129 
       
   130     ; Timed frames
       
   131         ; start frame
       
   132         rcall       DMX_Frame_Start
       
   133 
       
   134     ; ok
       
   135     ret
       
   136 
       
   137 ;; Bitbang one DMX bit out
       
   138 ;;  uses SREG/C to send
       
   139 ;
       
   140 ; Uses Timer2 as a bit sync clock, sending out the next bit once we've hit 64 cycles on the timer
       
   141 DMX_Bit:
       
   142     ; Wait for bit sync clock
       
   143 _dmx_bit_wait:
       
   144         ; test OCA hit
       
   145         sbic    TIFR2, OCF2A     
       
   146         rjmp    _dmx_bit_wait   
       
   147 
       
   148 ;sbi         LED_PORT, LED_BIT
       
   149 
       
   150     ; Output bit
       
   151         ; XXX: ugly bit-testing, can't we do this using something more nifty?
       
   152         brcs    _dmx_bit_1
       
   153         
       
   154         ; bit 0
       
   155         cbi     DMX_PORT, DMX_DATA
       
   156         rjmp    _dmx_bit_done
       
   157 
       
   158 _dmx_bit_1:
       
   159         ; bit 1
       
   160         sbi     DMX_PORT, DMX_DATA
       
   161         nop
       
   162 
       
   163     ; Bit sent
       
   164 _dmx_bit_done:
       
   165         ; reset OCA hit for next bit
       
   166         cbi     TIFR2, OCF2A
       
   167 
       
   168     ; OK, bit sync clock keeps running for next bit
       
   169     ret
       
   170 
       
   171 ;; Bitbang one DMX byte out, using DMX_Bit
       
   172 ;;  r16: byte value
       
   173 ;
       
   174 ; Uses Timer2 as a bit sync clock; must call DMX_Frame_Start before first DMX_Frame
       
   175 DMX_Frame:
       
   176     ; Start bit
       
   177         clc
       
   178         rcall       DMX_Bit
       
   179 
       
   180     ; Data bits: 8
       
   181         ldi         r21, 8
       
   182         
       
   183 _dmx_frame_loop:
       
   184         ; shift + send bit
       
   185         lsl         r16
       
   186         rcall       DMX_Bit
       
   187 
       
   188         ; loop
       
   189         dec         r21
       
   190         brne        _dmx_frame_loop
       
   191 
       
   192     ; Stop bits
       
   193         sec
       
   194         rcall       DMX_Bit
       
   195         rcall       DMX_Bit
       
   196     
       
   197     ; OK
       
   198     ret
       
   199 
       
   200 ;; End of DMX frames
       
   201 DMX_Frame_End:
       
   202     ; Keep mark from end of last frame; DMX_Break_Start starts the break
       
   203     ; Stop the timer
       
   204         poke        [DMX_TIMER_CRB, r20, (DMX_TIMER_WGM_2 << WGM22) | (DMX_TIMER_CS_STOP << CS20)]
       
   205 
       
   206     ; OK
       
   207     ret
       
   208 
       
   209 ;; Send one value on all frames
       
   210 ;;  r17: byte value
       
   211 DMX_Flood:
       
   212     ; Break
       
   213         rcall       DMX_Break
       
   214 
       
   215     ; Start code
       
   216         ldi         r16, 0
       
   217         rcall       DMX_Frame
       
   218 
       
   219     ; Channels
       
   220         ; number of channels to send
       
   221         ldi         r22, 100
       
   222 
       
   223 _dmx_flood_channels:
       
   224         ; restore channel value
       
   225         mov         r16, r17
       
   226 
       
   227         ; send channel value
       
   228         rcall       DMX_Frame
       
   229 
       
   230         ; loop
       
   231         dec         r22
       
   232         brne        _dmx_flood_channels
       
   233 
       
   234     ; End packet
       
   235         rcall       DMX_Frame_End
       
   236 
       
   237 
       
   238     ret
       
   239 
       
   240 ;; Program main
       
   241 Main:
       
   242 ; Initialization
       
   243     ; Debug
       
   244         sbi         LED_DDR, LED_BIT
       
   245 sbi         LED_PORT, LED_BIT
       
   246 
       
   247     ; Stack
       
   248 		poke		[SPL, r16:r17, RAMEND]
       
   249 
       
   250     ; Init
       
   251         rcall       DMX_Init
       
   252 
       
   253 cbi         LED_PORT, LED_BIT
       
   254 
       
   255     ; Send; value
       
   256 _main_loop:
       
   257         ldi         r17, 255
       
   258         rcall       DMX_Flood
       
   259 
       
   260 cbi         LED_PORT, LED_BIT
       
   261 
       
   262         ; never returns..
       
   263         rjmp        _main_loop
       
   264