;; No Fly Zone
;;
;; Copyright 2012 - By Michael Kohn
;; http://www.mikekohn.net/
;; mike@mikekohn.net
;;
;; Jam IR signals on SYMA S107 Helicopter when sensor detects controller.

;; Updated January 26, 2012

.include "msp430g2x31.inc"

; 2.0 ms = 152 interrupts
; 0.3 ms = 23 interrupts
; 0.6 ms = 46 interrupts

; HH YAW PTCH THROTTLE YAW_CORRECT
; YAW = 0-126  63
; PITCH = 0-126 63
; THROTTLE = 0-126
; CORR = 0-126 63

RAM equ 0x0200
HEADER equ 152
SHORT equ 23
LONG equ 46

;  r4 = state (0=idle, 1=header_on, 2=header_off, 3=first half, 4=second)
;  r5 = interupt count
;  r6 = pointer to next byte going out
;  r7 = current byte
;  r8 = bit count
;  r9 = bit time len
; r10 = LED to turn on (2,8,32,128)
; r11 =
; r12 =
; r13 = interrupt routine
; r14 =
; r15 =

  .org 0xf800
start:
  ;; Turn off watchdog
  mov.w #(WDTPW|WDTHOLD), &WDTCTL

  ;; Please don't interrupt me
  dint

  ;; r13 points to which interrupt routine should be called
  mov.w #led_off, r13

  ;; Set up stack pointer
  mov.w #0x0280, SP

  ;; Set MCLK to 16 MHz with DCO 
  mov.b #DCO_4, &DCOCTL
  mov.b #RSEL_15, &BCSCTL1
  mov.b #0, &BCSCTL2

.if 0
  ;; Set MCLK to 16 MHz external crystal
  bic.w #OSCOFF, SR
  bis.b #XTS, &BCSCTL1
  mov.b #LFXT1S_3, &BCSCTL3
  ;mov.b #LFXT1S_3|XCAP_1, &BCSCTL3
test_osc:
  bic.b #OFIFG, &IFG1
  mov.w #0x00ff, r15
dec_again:
  dec r15
  jnz dec_again
  bit.b #(OFIFG), &IFG1
  jnz test_osc
  mov.b #(SELM_3|SELS), &BCSCTL2
.endif

  ;; Set up output pins
  ;; P1.0 = IR Input
  ;; P1.1 = Data Out on IR LED 
  ;; P1.2 = IR Input
  ;; P1.3 = Data Out on IR LED 
  ;; P1.4 = IR Input
  ;; P1.5 = Data Out on IR LED 
  ;; P1.6 = IR Input
  ;; P1.7 = Data Out on IR LED 
  ;; P2.7 = Data Out on LED  (debug)
  mov.b #0xaa, &P1DIR
  mov.b #0, &P1OUT
  ;mov.b #2, &P1REN
  mov.b #128, &P2DIR
  mov.b #128, &P2OUT
  mov.b #0, &P2SEL

  ;; Set up Timer
  mov.w #210, &TACCR0
  mov.w #(TASSEL_2|MC_1), &TACTL ; SMCLK, DIV1, COUNT to TACCR0
  mov.w #CCIE, &TACCTL0
  mov.w #0, &TACCTL1

  mov.b #63, &RAM    ; Yaw
  mov.b #63, &RAM+1  ; Pitch
  mov.b #0, &RAM+2  ; Throttle
  mov.b #0, &RAM+3  ; Yaw correction

  ;; Okay, I can be interrupted now
  eint

main:
  mov.b &P1IN, r11
  and.b #0x55, r11
  cmp.b #0x55, r11
  ;cmp.b #0x55, &P1IN
  jz stop_sending
  mov.b #0xaa, r10
  ;mov.b #0x00, r10
  call #send_command
  ;call #send_all
  jmp main

stop_sending:
  mov.w #led_off, r13
  jmp main

;; this function sends to the 4 LED's in rotation to save on current draw
send_all:
  mov.b #2, r10
next_led:
  call #send_command
  ;rla r10               change LED's after every byte now instead
  ;rla r10
  jnz next_led
  ret

send_command:
  bic.b #128, &P2OUT
  mov.w #0, r5
  mov.w #led_on, r13
wait_header_on:
  cmp.w #HEADER, r5
  jl wait_header_on

  mov.w #0, r5
  mov.w #led_off, r13
wait_header_off:
  cmp.w #HEADER, r5
  jl wait_header_off

  mov.w #RAM, r6
send_next_byte:
  mov.b @r6+, r7
  mov.b #8, r8
send_next_bit:
  mov.w #LONG, r9
  rla.b r7
  ;rra.b r7
  jc it_was_a_1
  mov.w #SHORT, r9
it_was_a_1:

  mov.w #led_on, r13
  mov.w #0, r5
wait_on_first_half:
  cmp.w #SHORT, r5
  jl wait_on_first_half

  mov.w #led_off, r13
  mov.w #0, r5
wait_on_second_half:
  cmp.w r9, r5
  jl wait_on_second_half

  dec.b r8
  jnz send_next_bit

  ;rla r10
  ;rla r10

  cmp.w #RAM+4, r6
  jne send_next_byte

  mov.w #0, r5
pause:
  cmp.w #SHORT, r5
  jl pause
  bic.b #0xaa, &P1OUT
  bis.b #128, &P2OUT
  ret

timer_interrupt:
  br r13

led_on:
  xor.b r10, &P1OUT
  inc.w r5
  reti

led_off:
  bic.b #0xaa, &P1OUT
  inc.w r5
  reti

  org 0xffe8
vectors:
  dw 0
  dw 0
  dw 0
  dw 0
  dw 0
  dw timer_interrupt       ; Timer_A2 TACCR0, CCIFG
  dw 0
  dw 0
  dw 0
  dw 0
  dw 0
  dw start                 ; Reset



