led7seg.s
changeset 17 a7c668003a19
parent 16 11d6167a67cb
child 18 79b25e81721f
equal deleted inserted replaced
16:11d6167a67cb 17:a7c668003a19
    11 
    11 
    12 .org ADCCaddr
    12 .org ADCCaddr
    13         rjmp        ADC_Interrupt
    13         rjmp        ADC_Interrupt
    14 
    14 
    15 ;; SPI
    15 ;; SPI
    16 .equ SPI_DDR    = DDRB
    16 .include "spi.inc"
    17 .equ SPI_PORT   = PORTB
       
    18 .equ SPI_SCK    = PORTB5
       
    19 .equ SPI_MISO   = PORTB4
       
    20 .equ SPI_MOSI   = PORTB3
       
    21 .equ SPI_SS     = PORTB2
       
    22 
       
    23 .equ SPI_FLAGS  = GPIOR0
       
    24 .equ SPI_BUSY   = 0
       
    25 
       
    26 ;; Initialize SPI subsystem for master operation
       
    27 SPI_Init:
       
    28     ; Set modes
       
    29         sbi         SPI_DDR, SPI_SCK        ; Out
       
    30         sbi         SPI_DDR, SPI_MOSI       ; Out
       
    31         sbi         SPI_DDR, SPI_SS         ; Out
       
    32 
       
    33     ; Drive SS high (off)
       
    34         sbi         SPI_PORT, SPI_SS
       
    35 
       
    36     ; Set control mode
       
    37         ; Enable interrupt
       
    38         ; Enable SPI
       
    39         ; MSB first
       
    40         ; Master mode
       
    41         ; Polarity/phase: Mode 0 (sample on rising edge)
       
    42         ; Clock rate 1/16
       
    43         ldi         r16, (1 << SPIE) | (1 << SPE) | (0 << DORD) | (1 << MSTR) | (0 << CPOL) | (0 << CPHA) | (0b01 << SPR0)
       
    44         out         SPCR, r16
       
    45     
       
    46     ; Flags
       
    47         clr         r0
       
    48         out         SPI_FLAGS, r0
       
    49     
       
    50     ; Done
       
    51         ret
       
    52 
       
    53 ;; Send byte
       
    54 ;;  Input: r16
       
    55 ;;  XXX: should not be busy...
       
    56 SPI_SendRecv:
       
    57     ; Flag
       
    58         sbi         SPI_FLAGS, SPI_BUSY
       
    59 
       
    60     ; Enable slave (low)
       
    61         cbi         SPI_PORT, SPI_SS
       
    62     
       
    63     ; Write byte (starts SCK)
       
    64         out         SPDR, r16
       
    65     
       
    66     ; Wait for interrupt
       
    67     ; Done
       
    68         ret
       
    69 
       
    70 ;; Wait for byte to be sent
       
    71 SPI_Wait:
       
    72 wait_idle:
       
    73         sbic        SPI_FLAGS, SPI_BUSY     ; Test for busy flag
       
    74         rjmp        wait_idle               ; loop
       
    75         
       
    76     ; Done
       
    77         ret
       
    78 
       
    79 ;; Service SPI interrupt
       
    80 SPI_Interrupt:
       
    81     ; Store SREG
       
    82         in          r16, SREG
       
    83 
       
    84     ; Drive SS high (off)
       
    85         sbi         SPI_PORT, SPI_SS
       
    86 
       
    87     ; Read
       
    88         in         r10, SPDR
       
    89 
       
    90     ; Flag
       
    91         cbi         SPI_FLAGS, SPI_BUSY
       
    92 
       
    93     ; Done
       
    94         out         SREG, r16
       
    95         reti
       
    96 
    17 
    97 ;; LCD
    18 ;; LCD
    98 .equ LCD_DDR    = DDRB
    19 .include "led7seg.inc"
    99 .equ LCD_PORT   = PORTB
       
   100 .equ LCD_OE     = PORTB1                ; Output Enable (Low)
       
   101 
       
   102 ; Output font for 7-segment display
       
   103 LCD_Font:
       
   104 .db     0b00111111, 0b00000110      ; 0, 1
       
   105 .db     0b01011011, 0b01001111      ; 2, 3
       
   106 .db     0b01100110, 0b01101101      ; 4, 5
       
   107 .db     0b01111101, 0b00000111      ; 6, 7
       
   108 .db     0b01111111, 0b01100111      ; 8, 9
       
   109 .db     0b01110111, 0b01111100      ; A, b
       
   110 .db     0b00111001, 0b01011110      ; C, d
       
   111 .db     0b01111001, 0b01110001      ; E, f
       
   112 .db     0b10000000, 0b00000000      ; ., 
       
   113 
       
   114 ;.db     0b00111111,     ; 0
       
   115 ;        0b00000110,     ; 1
       
   116 ;        0b01011011,     ; 2
       
   117 ;        0b01001111,     ; 3
       
   118 ;        0b01100110,     ; 4
       
   119 ;        0b01101101,     ; 5
       
   120 ;        0b01111101,     ; 6
       
   121 ;        0b00000111,     ; 7
       
   122 ;        0b01111111,     ; 8
       
   123 ;        0b01100111,     ; 9
       
   124 ;        0b10000000,     ; .
       
   125 ;        0b01000000      ; 
       
   126 
       
   127 .equ LCD_0      = 0
       
   128 .equ LCD_1      = 1
       
   129 .equ LCD_2      = 2
       
   130 .equ LCD_3      = 3
       
   131 .equ LCD_4      = 4
       
   132 .equ LCD_5      = 5
       
   133 .equ LCD_6      = 6
       
   134 .equ LCD_7      = 7
       
   135 .equ LCD_8      = 8
       
   136 .equ LCD_9      = 9
       
   137 .equ LCD_A      = 10
       
   138 .equ LCD_B      = 11
       
   139 .equ LCD_C      = 12
       
   140 .equ LCD_D      = 13
       
   141 .equ LCD_E      = 14
       
   142 .equ LCD_F      = 15
       
   143 .equ LCD_DOT    = 16
       
   144 .equ LCD_EMPTY  = 17
       
   145 
       
   146 ;; Initialize LCD to empty, and enable
       
   147 LCD_Init:
       
   148     ; Setup ENable port
       
   149         sbi         LCD_PORT, LCD_OE    ; Disabled (Low)
       
   150         sbi         LCD_DDR, LCD_OE     ; Out
       
   151 
       
   152         ; empty
       
   153         ldi         r16, 0b11111111
       
   154 
       
   155     ; Output
       
   156         rcall       SPI_SendRecv
       
   157         rcall       SPI_Wait
       
   158 
       
   159     ; Enable
       
   160         cbi         LCD_PORT, LCD_OE
       
   161 
       
   162     ; Done
       
   163         ret
       
   164 
       
   165 ;; Display a single digit on the display
       
   166 ;;  Input: r16
       
   167 LCD_Show:
       
   168         clr         r0, 0
       
   169 
       
   170     ; Prep address
       
   171         ; base addr for font table
       
   172         ldi         ZH, high(2*LCD_Font)
       
   173         ldi         ZL, low(2*LCD_Font)
       
   174         
       
   175         ; offset
       
   176         add         ZL, r16
       
   177         adc         ZH, r0
       
   178 
       
   179     ; Load char
       
   180         lpm         r16, Z
       
   181     
       
   182     ;; Continue
       
   183 
       
   184 ;; Display a raw segment mask
       
   185 ;;  Input: r16
       
   186 LCD_ShowRaw:
       
   187     ; Invert
       
   188         ; com         r16
       
   189 
       
   190     ; Display
       
   191         rjmp        SPI_SendRecv
       
   192 
    20 
   193 ;; ADC
    21 ;; ADC
   194 .equ ADC_DDR    = DDRC
    22 .include "adc.inc"
   195 .equ ADC_PORT   = PORTC
       
   196 .equ ADC_PIN    = PORTC0
       
   197         
       
   198 ;; Initialize the ADC for starting conversions
       
   199 ADC_Init:
       
   200     ; Setup ADMUX
       
   201         ; Use AVcc as ref
       
   202         ; Left-adjust result (for 8-bit access)
       
   203         ; Select ADC0
       
   204         ldi         r16, (0b01 << REFS0) | (1 << ADLAR) | (0b000 << MUX0)
       
   205         sts         ADMUX, r16
       
   206     
       
   207     ; Setup ADCSRB
       
   208         ; Free-running mode
       
   209         ldi         r16, (0b000 << ADTS0)
       
   210         sts         ADCSRB, r16
       
   211 
    23 
   212     ; Setup ADCSRA
    24 ;; Utils
   213         ; Enable
    25 .include "delay.inc"
   214         ; Start right away...
       
   215         ; Auto-trigger
       
   216         ; Enable Interrupt
       
   217         ; Scale 1/128
       
   218         ldi         r16, (1 << ADEN) | (1 << ADSC) | (1 << ADATE) | (1 << ADIE) | (0b111 << ADPS0)
       
   219         sts         ADCSRA, r16
       
   220 
       
   221     ; Disable digital circuit for pin
       
   222         ldi         r16, (1 << ADC_PIN)
       
   223         sts         DIDR0, r16
       
   224 
       
   225     ; Debug LED
       
   226         sbi         DDRD, PORTD7
       
   227         sbi         PORTD, PORTD7
       
   228 
       
   229     ; Done
       
   230         ret
       
   231 
       
   232 ADC_Interrupt:
       
   233     ; Off
       
   234         cbi         PORTD, PORTD7
       
   235     
       
   236     ; Done
       
   237         reti    
       
   238 
       
   239 ;; Read the current 8-bit ADC sample 
       
   240 ; Returns value in r16
       
   241 ADC_Read8:
       
   242     ; Copy
       
   243         lds         r16, ADCH
       
   244 
       
   245     ; Done
       
   246         ret
       
   247 
       
   248 ;; Delay for approx. one second
       
   249 Delay_1s:
       
   250         ; 40 * 64k = 2.6M loops
       
   251         ldi         r20, 40
       
   252 
       
   253 ;; Delay for r20 * 64k cycles
       
   254 VarDelay:
       
   255         ldi         r21, 255
       
   256 
       
   257 ;; Delay for r20 * r21 * 255 cycles
       
   258 ShortDelay:
       
   259         ldi         r22, 255
       
   260 
       
   261 delay:
       
   262         dec         r22
       
   263         brne        delay
       
   264         dec         r21
       
   265         brne        delay
       
   266         dec         r20
       
   267         brne        delay
       
   268 
       
   269         ret
       
   270 
       
   271 
    26 
   272 ;; Count down from 9
    27 ;; Count down from 9
   273 ; Returns once we've hit zero
    28 ; Returns once we've hit zero
   274 Main_Countdown:
    29 Main_Countdown:
   275         ; init from F
    30         ; init from F
   276         ldi         r24, LCD_F
    31         ldi         r24, LED7_F
   277 
    32 
   278 _count_loop:
    33 _count_loop:
   279         ; display
    34         ; display
   280         mov         r16, r24
    35         mov         r16, r24
   281         rcall       LCD_Show
    36         rcall       LED7_Show
   282 
    37 
   283         ; exit if zero
    38         ; exit if zero
   284         tst         r24
    39         tst         r24
   285         breq        _count_end
    40         breq        _count_end
   286 
    41 
   299 
    54 
   300 ;; Blink between dot and empty
    55 ;; Blink between dot and empty
   301 Main_Blink:
    56 Main_Blink:
   302 _blink_loop:
    57 _blink_loop:
   303         ; dot
    58         ; dot
   304         ldi         r16, LCD_DOT
    59         ldi         r16, LED7_DOT
   305         rcall       LCD_Show
    60         rcall       LED7_Show
   306 
    61 
   307         ; wait...
    62         ; wait...
   308         rcall       Delay_1s
    63         rcall       Delay_1s
   309         
    64         
   310         ; empty
    65         ; empty
   311         ldi         r16, LCD_EMPTY
    66         ldi         r16, LED7_EMPTY
   312         rcall       LCD_Show
    67         rcall       LED7_Show
   313         
    68         
   314         rcall       Delay_1s
    69         rcall       Delay_1s
   315         
    70         
   316         ; loop
    71         ; loop
   317         rjmp        _blink_loop
    72         rjmp        _blink_loop
   323         ldi         r24, 0b00000001 
    78         ldi         r24, 0b00000001 
   324 
    79 
   325 _spin_next:
    80 _spin_next:
   326         ; display
    81         ; display
   327         mov         r16, r24
    82         mov         r16, r24
   328         rcall       LCD_ShowRaw
    83         rcall       LED7_ShowRaw
   329 
    84 
   330         ; variable delay -> r16
    85         ; delay from ADC
   331         ;rcall       ADC_Read8
    86         ;rcall       ADC_Read8
   332         ;mov         r20, r16
    87         ;mov         r20, r16
   333 
    88 
   334         ; delay from input
    89         ; delay from input
   335         mov         r20, r10
    90         mov         r20, r10
   336         
    91         
   337         ; constant
    92         ; constant
   338         ;ldi         r20, 20
    93         ;ldi         r20, 20
   339 
    94 
   340         ; short delay, from ADC
    95         ; short delay
   341         ldi         r21, 255
    96         rcall       VarDelay
   342         rcall       ShortDelay
       
   343 
    97 
   344         ; next segment
    98         ; next segment
   345         lsl         r24
    99         lsl         r24
   346         
   100         
   347         ; go back to A if we hit G
   101         ; go back to A if we hit G
   366 
   120 
   367     ; SPI
   121     ; SPI
   368         rcall       SPI_Init
   122         rcall       SPI_Init
   369     
   123     
   370     ; LCD (requires interrupts, blocks)
   124     ; LCD (requires interrupts, blocks)
   371         rcall       LCD_Init    
   125         rcall       LED7_Init    
   372     
   126     
   373     ; Run
   127     ; Run
   374         ; spin!
   128         ; spin!
   375         ;rcall       Main_Spin
   129         rcall       Main_Spin
   376         
   130         
   377         ; count!
   131         ; count!
   378         rcall       Main_Countdown
   132         ; rcall       Main_Countdown
   379         rcall       Main_Blink
   133         ; rcall       Main_Blink
   380 
   134 
   381 end:
   135 end:
   382         rjmp        end
   136         rjmp        end
   383 
   137