; defines & equals
.def zero = r0
.def one = r1
+.def countrgb = r2
+.def desc = r3
+.equ RUP = 0
+.equ RDOWN = 1
+.equ GUP = 2
+.equ GDOWN = 3
+.equ BUP = 4
+.equ BDOWN = 5
.def tmp = r16
.def uart_count = r17
.def count = r18
.equ rgb = 1
.def OUTR = r23
.def FULLR = r24
+.def tmp2 = r25
.equ LED_R = PD2
.equ LED_G = PD3
.equ LED_B = PD4
.equ LED_PORT = PORTD
+.equ CM1 = 85
+.equ CM2 = 170
;
; interrupt voctors
; timer/counter compare
reti
; timer/counter overflow 1
-rjmp INC_RGB
+rjmp DO_IT
; timer/counter overflow 0
reti
; uart rx complete
; alloc stack pointer
ldi r16,low(RAMEND)
out SPL,r16
-; timer: clock/1024
+; timer: clock/8
ldi tmp,((1<<CS11))
out TCCR1B,tmp
; enable timer overflow interrupt
; enable uart + rx complete interrupt
ldi tmp,51 ; 9600 baud, 0,2% error @ 8mhz
out UBRR,tmp
-ldi tmp,((1<<RXCIE)|(1<<RXEN))
+ldi tmp,((1<<RXCIE)|(1<<RXEN)|(1<<TXEN))
out UCR,tmp
; init registers
ldi tmp,1
mov one,tmp
ldi tmp,0
mov zero,tmp
+mov countrgb,tmp
ldi uart_count,0
ldi count,0
-ldi RED,0x22
-ldi GREEN,0x77
-ldi BLUE,0xff
+ldi RED,CM2
+ldi GREEN,0x0
+ldi BLUE,0x0
; led pins are outputs
ldi tmp,((1<<LED_R)|(1<<LED_G)|(1<<LED_B))
out DDRD,tmp
+; default mode: cm
+ldi mode,cm
; enable interrupts (global)
sei
; jump to main
rjmp MAIN
;
-; increase rgb values
+; decide what to do
;
-INC_RGB:
-add RED,one
-add BLUE,one
-add GREEN,one
+DO_IT:
+cpi mode,cm
+breq CM_ACTION
+reti
+
+;
+; specify action
+;
+
+
+;
+; continuous mode action
+;
+CM_ACTION:
+cp countrgb,zero
+breq RD_GU
+ldi tmp,CM1
+cp countrgb,tmp
+breq GD_BU
+ldi tmp,CM2
+cp countrgb,tmp
+breq BD_RU
+ldi tmp,255
+cp countrgb,tmp
+breq RESET_RGB
+rjmp MAKE_RGB
+
+;
+; reset rgb
+;
+RESET_RGB:
+ldi RED,CM2
+mov GREEN,zero
+mov BLUE,zero
+mov desc,zero
+rjmp MAKE_RGB
+
+;
+; set desc
+;
+RD_GU:
+ldi tmp,((1<<RDOWN)|(1<<GUP))
+mov desc,tmp
+rjmp MAKE_RGB
+GD_BU:
+ldi tmp,((1<<GDOWN)|(1<<BUP))
+mov desc,tmp
+rjmp MAKE_RGB
+BD_RU:
+ldi tmp,((1<<BDOWN)|(1<<RUP))
+mov desc,tmp
+rjmp MAKE_RGB
+
+;
+; do the actual rgb calculation
+;
+MAKE_RGB:
+ldi tmp,(1<<RUP)
+and tmp,desc
+add tmp,tmp
+add RED,tmp
+ldi tmp,(1<<GUP)
+and tmp,desc
+lsr tmp
+lsr tmp
+add tmp,tmp
+add GREEN,tmp
+ldi tmp,(1<<BUP)
+and tmp,desc
+lsr tmp
+lsr tmp
+lsr tmp
+lsr tmp
+add tmp,tmp
+add BLUE,tmp
+ldi tmp,(1<<RDOWN)
+and tmp,desc
+lsr tmp
+add tmp,tmp
+sub RED,tmp
+ldi tmp,(1<<GDOWN)
+and tmp,desc
+lsr tmp
+lsr tmp
+lsr tmp
+add tmp,tmp
+sub GREEN,tmp
+ldi tmp,(1<<BDOWN)
+and tmp,desc
+lsr tmp
+lsr tmp
+lsr tmp
+lsr tmp
+lsr tmp
+add tmp,tmp
+sub BLUE,tmp
+add countrgb,one
reti
;
; main routine
;
MAIN:
-; jumpt to main loop
+; jump to main loop
rjmp LOOP
:
; reset leds
;
RESET_LEDS:
-ldi OUTR,((1<<LED_R)|(1<<LED_G)|(LED_B))
+ldi OUTR,((1<<LED_R)|(1<<LED_G)|(1<<LED_B))
rjmp CHECK_RED
;
; receive from uart
;
UART_RECEIVE:
+cp uart_count,zero
+breq GET_MODE
+cpi uart_count,1
+breq GET_R_VALUE
+cpi uart_count,2
+breq GET_G_VALUE
+cpi uart_count,3
+breq GET_B_VALUE
+
+;
+; get mode
+;
+GET_MODE:
+in tmp,UDR
+cpi tmp,0x63 ; 0x63 = 'c'
+breq SET_CONTINUOUS_MODE
+cpi tmp,0x73 ; 0x73 = 's'
+breq SET_SPECIFY_MODE
+ldi uart_count,0
+reti
+
+;
+; set cmode
+;
+SET_CONTINUOUS_MODE:
+ldi mode,cm
+ldi uart_count,0
+reti
+
+;
+; set specify mode
+;
+SET_SPECIFY_MODE:
+ldi mode,rgb
+add uart_count,one
+; check
+out UDR,mode
+reti
+
+;
+; get red value
+;
+GET_R_VALUE:
+in RED,UDR
+add uart_count,one
+; check
+out UDR,RED
+reti
+
+;
+; get green value
+;
+GET_G_VALUE:
+in GREEN,UDR
+add uart_count,one
+; check
+out UDR,GREEN
+reti
+
+;
+; get blue value
+;
+GET_B_VALUE:
+in BLUE,UDR
+mov uart_count,zero
+; check
+out UDR,BLUE
reti