;    Port Locations
;    PORTB
;          0: out, Motor 1     LOW=Motor enabled
;          1: out, Motor 2            "
;          2: out, Motor 3            "
;          3: out, Motor 4            "
;          4: out, Coil 1          LOW=on
;          5: out, Coil 2             "
;          6: out, Coil 3             "
;          7: out, Coil 4             "
;
;          
;    PORTD General
;          0: in,  RXD from RF receiver
;          1: out, any function
;          2: out,
;          3: out,
;          4: out,
;          5: out,
;          6: out, button 1 pressed
;
;    Commands that are received:
;    lower nibble = function 1-4
;    upper nibble: 0000:   rotator left
;                  0001:   rotator right
;                  1110:   button 1 pressed
;                  1100:   button 2 pressed
;                  1010:   button 3 pressed
;
.equ OffTime=220
.equ Direction=4              ; rotating direction bit in received command
.include "2313def.inc"
.def NoEqu=r18                 ; Counts the number of equal commands 
.def LastRecCommand=r11
.def ReceivedCommand=r21       ; Holds the last received command
.def argument0=r19             ; Argument for subroutine calls
.def temp1=r20
.def temp=r16
.def Motor1Status=r17
;**************************** code begins here *********************************
       rjmp reset
       reti                    ; external interrupt 0
       reti                    ; external interrupt 1
       reti                    ; timer 1 capture
       reti                    ; timer 1 compare
       rjmp SwitchOffMotor     ; timer 1 overflow
       reti                    ; timer 0 overflow
       rjmp Receive            ; uart rx complete
       reti                    ; uart urd empty
       reti                    ; uart tx complete
       reti                    ; comperator
;*********************************** Receive **********************************
Receive:
       in ReceivedCommand,UDR             ; Get received data
       cp ReceivedCommand,LastRecCommand  ; Compare with last command
       brne NotEqual
       inc NoEqu                          ; Count if they are equal
       cpi NoEqu,0x04                     ; 5 times equal command received ?
       brne EndReceive        
       cpi ReceivedCommand,0x00           ; Reject zeros
       breq NotEqual                      
       rcall DecodeCommand                ; Execute command if yes
       ldi temp,0xFF
       mov ReceivedCommand,temp
NotEqual:
       clr NoEqu                          ; Reset counter if different
EndReceive:
       mov LastRecCommand,ReceivedCommand ; Store last command
       reti
;******************************* DecodeCommand ********************************
DecodeCommand:
       ldi R31,0x01                       ; Location of jump table
       mov R30,ReceivedCommand            ; load command into address register
       lsr R30
       lsr R30
       lsr R30
       lsr R30
       icall
       ret       
;******************************* RotateLeft ***********************************
RotateLeft:
       rcall ResetSleepCounter
       ldi R31,0x00
       mov R30,ReceivedCommand
       andi R30,0x0F
       ori R30,0x60
       ld temp,Z
       cpi temp,0x00
       breq EndRotateLeft
       lsl temp
       brne NotAtEnd
       ldi temp,0x10
NotAtEnd:
       st Z,temp
       mov temp1,ReceivedCommand      ; get the command again for the function
;       com temp1                      ; invert it because we use 7400      
       andi temp1,0x0F                ; the function is in the last nibble 
       or temp,temp1
       com temp
       out PORTB,temp
EndRotateLeft:       
       ret
;******************************* RotateRight **********************************
RotateRight:
       rcall ResetSleepCounter
       ldi R31,0x00                    ;
       mov R30,ReceivedCommand         ;
       andi R30,0x0F                   ;
       ori R30,0x60                    ;
       ld temp,Z                       ;
       cpi temp,0x00
       breq EndRotateRight
       lsr temp
       andi temp,0xF0
       brne NotAtBegin
       ldi temp,0x80
NotAtBegin:
       st Z,temp
       mov temp1,ReceivedCommand
;       com temp1                      ; invert it because we use 7400   
       andi temp1,0x0F
       or temp,temp1
       com temp
       out PORTB,temp
EndRotateRight:       
       ret
;******************************* Button1Pressed *******************************
Button1Pressed:
       ldi temp, 0b0111111
       out PORTD, temp
       ret
;******************************* Button3Pressed *******************************
Button2Pressed:
       ldi temp, 0b1111111
       out PORTD, temp
       ret
;******************************* Button3Pressed *******************************
Button3Pressed:
       nop
       ret
;******************************* Button4Pressed *******************************
Button4Pressed:
       nop
       ret
;******************************* SwitchOffMotor *******************************
SwitchOffMotor:
       ldi temp,0xFF
       out PORTB,temp          ; switch off all coils
       reti
;******************************* ResetSleepTimer *******************************
ResetSleepCounter:
       ldi temp,OffTime        ; Starting value for counter 1
       ldi temp1,0x00
       out TCNT1H,temp
       out TCNT1L,temp1
       ret
;***************************** Init *******************************************
init:  
       ldi temp,0b11111111     ; Set outputs for motors
       out DDRB,temp
       ldi temp,0xFF           ; Switch all coils off
       out PORTB,temp          ; 
       ldi temp,0b11111110     ; set all output except RXD
       out DDRD,temp
       sbi UCR,RXEN            ; allow UART recive
       sbi UCR,RXCIE           ; allow RX interrupt
       ldi temp,143            ; set 4800 baud at 11MHz
       out UBRR,temp
       sbi ACSR,ACD	       ; shut down comparator to save power
       ldi temp,0xFF           ; clear all accidentally occurd interrupts
       out GIFR,temp
       ldi temp,0x80
       sts 0x0061,temp
       sts 0x0062,temp
       sts 0x0064,temp
       sts 0x0068,temp
       clr NoEqu
;       ldi temp,0b00000001     ; Prescaler Counter 1 1024
       ldi temp,0b00000101     ; Prescaler Counter 1 1024
       out TCCR1B,temp
       rcall ResetSleepCounter
       ldi temp,0b10000000     ; Timer1 overflow Interupt enable
       out TIMSK,temp
       rcall SwitchOffMotor
       sei                     ; Enable interupts globally
       ret
;******************************** main **********************************
reset:  
       ldi temp,RAMEND         ; Initialize stack pointer
       out SPL,temp
       rcall init              ; Initialize CPU and variables
mloop: 
       rjmp mloop

.org 0x0100
       rjmp RotateLeft         ; 0000
       rjmp RotateRight        ; 0001
       ret                     ; 0010
       ret                     ; 0011
       ret                     ; 0100
       ret                     ; 0101
       ret                     ; 0110
       ret                     ; 0111
       rjmp Button4Pressed     ; 1000
       ret                     ; 1001
       rjmp Button3Pressed     ; 1010
       ret                     ; 1011
       rjmp Button2Pressed     ; 1100
       ret                     ; 1101
       rjmp Button1Pressed     ; 1110
       ret                     ; 1111
       
       
       
       