SHARE
TWEET

Untitled

a guest Jan 5th, 2017 64 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2. Name: main.S
  3. Project: Monster B Gone
  4. $Author$
  5. Creation Date: 2016-10-02
  6. Tabsize: 4
  7. Copyright: License: GNU GPL v2 (see License.txt)
  8. This Revision: $Id$
  9. $Log$
  10. */
  11.  
  12. /*
  13. The code reads the calibration byte from the first eeprom address,
  14. put there by the Makefile during programming.
  15. Program first calls the random number generator, gets the number of
  16. pixel rolls to do in blue (minimum 3 tours).
  17. Frame pause should be bigger than 50ms, better between 100ms and
  18. 200ms.
  19. After all the rolls, stays green for 3 seconds, then shutsdown and
  20. sleeps until new reset.
  21.  
  22. Driving the neopixel:
  23. Timer T1 works in PWM mode for driving a neopixel each clock
  24. with Timer 1 clock at 156.25ns. The rotine is tightly timed, disable
  25. ints and do nothing else.
  26. for latching and waiting uses T0 to sleep for 200ms.
  27. */
  28.  
  29. #define __SFR_OFFSET 0
  30. #include <avr/io.h>
  31. #include <avr/eeprom.h>
  32.  
  33. /*
  34.     EEPROM
  35. */
  36.  
  37. /*
  38.     IO Definitions
  39. */
  40. #define NEOPIXEL    PB1     /* output to neopixel data */
  41. #define ENABLE_5    PB0     /* enable 5V supply */
  42.  
  43. /*
  44.     Constants
  45. */
  46. #define ZERO 0
  47. #define num_leds 12         /* number of leds in the ring (up to 16) */
  48.  
  49.  
  50. /* Time system constants */
  51.  
  52. /*
  53.     Register definition, use only C-style comments (avr-as is stupid)
  54. */
  55. ; from R0-R15 only direct addressing
  56. #define zero    R0          /* this register is always zero */
  57.  
  58. #define rnd_a   R1          /* random number generator register A */
  59. #define rnd_b   R2          /* random number generator register B */
  60. #define rnd_c   R3          /* random number generator register C */
  61. #define rnd_d   R4          /* random number generator register D */
  62. #define rnd_xor R5          /* random number generator auxiliary register */
  63.  
  64. #define G0      R6          /* working shift for green for ring */
  65. #define G1      R7
  66. #define R0      R8          /* working shift for red for ring */
  67. #define R1      R9
  68. #define B0      R10         /* working shift for blue for ring */
  69. #define B1      R11
  70.  
  71. #define SEND0   R12         /* values to reload counters */
  72. #define SEND1   R13         /* values to reload counters */
  73.  
  74. #define sw_prss R14         /* number of times reset pressed */
  75.  
  76. ; from R16-R31 ldi possible
  77. #define wreg    R16         /* working register */
  78.  
  79.  
  80. /* shifting colours in this order GRB, msb first */
  81. #define GREEN0  R17         /* intensity color for green 8 bits */
  82. #define GREEN1  R18
  83. #define RED0    R19         /* intensity for colour red */
  84. #define RED1    R20
  85. #define BLUE0   R21         /* intensity for colour blue */
  86. #define BLUE1   R22
  87. #define led_cnt R23         /* led counter */
  88. #define count   R24         /* counter for number of rounds */
  89. #define count_t R25         /* counter for timing loop */
  90.  
  91. /*
  92.     Interrupt Routines
  93. */
  94. ;* Addresses of interrupt routines is defined in io.h (for this processor)
  95. ;.global INT0_vect
  96. ;.global IO_PINS_vect
  97. ;.global TIMER1_COMP_vect
  98. ;.global TIMER1_OVF_vect
  99. ;.global TIMER0_OVF_vect
  100. ;.global EE_RDY_vect
  101. ;.global ANA_COMP_vect
  102. ;.global ADC_vect
  103.  
  104. .text
  105.  
  106. ;*
  107. ;* Interrupt 0
  108. ;*
  109. .global INT0_vect
  110. INT0_vect:
  111.     reti
  112.    
  113. ;*
  114. ;* Pin change interrupt
  115. ;*
  116. .global IO_PINS_vect
  117. IO_PINS_vect:
  118.     reti
  119.  
  120. ;*
  121. ;* Interrupt Timer 1 Overflow
  122. ;*
  123. .global TIMER1_OVF_vect
  124. TIMER1_OVF_vect:
  125.     reti
  126.    
  127. ;*
  128. ;* Interrupt Timer 1 Compare
  129. ;*
  130. .global TIMER1_COMP_vect
  131. TIMER1_COMP_vect:
  132.         reti
  133.    
  134. ;*
  135. ;* Interrupt Timer 0 Overflow
  136. ;*
  137. .global TIMER0_OVF_vect
  138. TIMER0_OVF_vect:
  139.     reti   
  140.  
  141. ;*
  142. ;* EEPROM ready interrupt
  143. ;*
  144. .global EE_RDY_vect
  145. EE_RDY_vect:
  146.     reti
  147.    
  148. ;.global ANA_COMP_vect 
  149. ;*
  150. ;* Analog Comparator Interrupt
  151. ;*
  152. .global ANA_COMP_vect
  153. ANA_COMP_vect:
  154.     reti   
  155.    
  156. ;*
  157. ;* ADC Converter, End of Convertion
  158. ;*
  159. .global ADC_vect
  160. ADC_vect:
  161.     reti
  162.  
  163. ;*
  164. ;* Main routine
  165. ;*
  166. .global main
  167. main:
  168.     clr zero                ; register zero is always zero
  169. start:
  170.     rcall rnd_init          ; check and correct locking value
  171.     rcall random            ; get a new random number
  172.     rcall init_io           ; initialize IO system and unmutable variables
  173.     inc sw_prss             ; increment number of pressed switches
  174.     rcall wr_latch
  175.     rcall wr_latch
  176.     rcall wr_latch
  177.     rcall wr_latch          ; wait 800ms for a second reset
  178.    
  179.     mov wreg,sw_prss
  180.     cpi wreg,0x3            ; if sw_press > 0x02
  181.     brcc white_lgt          ; jump white light
  182.    
  183. seeking:
  184.     mov count, rnd_a        ; load lsb
  185.     andi count, 0x0F        ; max is 16
  186.     inc count               ; minimum 3 turns
  187.     inc count
  188.     inc count
  189.  
  190. sk_bg_loop:
  191.     ldi BLUE0,0x01          ; set one blue light on
  192.     clr BLUE1
  193.     clr GREEN0              ; clear all green
  194.     clr GREEN1
  195.     clr RED0                ; clear all red
  196.     clr RED1
  197.    
  198. sk_loop:                    ; seeking for monsters loop
  199.     rcall wr_frame          ; update
  200.     rcall wr_latch
  201.    
  202. mv_light:                   ;move the blue LED
  203.     lsl BLUE0
  204.     rol BLUE1
  205.     mov wreg,BLUE1
  206.     andi wreg,0xf0          ; test if at end of light loop
  207.     brne mv_lg_nx           ; if so start again
  208.     rjmp sk_loop
  209.    
  210. mv_lg_nx:
  211.     dec count
  212.     breq no_monster
  213.     rjmp sk_bg_loop
  214.    
  215. no_monster:                 ; everthing goes green
  216.     clr sw_prss
  217.     clr BLUE0
  218.     clr BLUE1
  219.     ldi wreg,0xff
  220.     mov GREEN0,wreg
  221.     mov GREEN1,wreg
  222.  
  223.     rcall wr_frame          ; update
  224.     rcall wr_latch
  225.    
  226.     ldi count_t,50          ; 5 * 10 * 200ms = 10s
  227. no_monst_10:
  228.     rcall wr_latch
  229.     dec count_t
  230.     brne no_monst_10
  231.  
  232.     mov GREEN0,zero         ; clear string
  233.     mov GREEN1,zero
  234.     rcall wr_frame          ; update
  235.     rcall wr_latch
  236.  
  237.     out PORTB,zero          ; shut down converter
  238.  
  239.     ldi wreg,0x30
  240.     out MCUCR,wreg          ; sleep mode power-down
  241.    
  242.     sleep                   ; only leaves with reset
  243.     nop
  244.    
  245. ;*********************************************************************************************
  246. ;* white_lgt
  247. ;*********************************************************************************************
  248. white_lgt:
  249.     clr sw_prss
  250.     ldi wreg,0xff
  251.     mov BLUE0,wreg              ; all blue
  252.     mov BLUE1,wreg
  253.     mov GREEN0,wreg             ; all green
  254.     mov GREEN1,wreg
  255.     mov RED0,wreg               ; all red
  256.     mov RED1,wreg
  257.    
  258.     rcall wr_frame              ; update
  259.     rcall wr_latch
  260.    
  261.     rcall wr_frame              ; update
  262.     rcall wr_latch
  263.  
  264.     ldi count_t,100         ; 100 * 200ms = 20s
  265. white_lgt_lp:
  266.     rcall wr_latch
  267.     dec count_t
  268.     brne white_lgt_lp
  269.    
  270.     clr BLUE0           ; set one blue light on
  271.     clr BLUE1
  272.     clr GREEN0              ; clear all green
  273.     clr GREEN1
  274.     clr RED0                ; clear all red
  275.     clr RED1
  276.  
  277.     rcall wr_frame          ; update
  278.     rcall wr_latch
  279.  
  280.     rcall wr_frame          ; update
  281.     rcall wr_latch
  282.    
  283.     out PORTB,zero          ; shutdown converter
  284.  
  285.     ldi wreg,0x30
  286.     out MCUCR,wreg          ; sleep mode power-down
  287.    
  288.     sleep                   ; only leaves with reset
  289.     nop
  290. ;*********************************************************************************************
  291. ;* init_io
  292. ;********************************************************************************************* 
  293. ; Initialize all the IO system, write IO values and unmutable variables.
  294. ; uses wreg,SEND0,SEND1    
  295. ;*********************************************************************************************
  296. init_io:
  297.     out EEAR,zero           ; get calibration byte from eeprom(0)
  298.     sbi EECR,EERE           ; strobe a read
  299.     in wreg,EEDR            ; get value from eeprom(0)     
  300.     out OSCCAL,wreg         ; set calibration byte @ 1.6MHz +/- 1%
  301.  
  302.     ldi wreg,0x03           ; PB1 must be programmed as output to work
  303.     out DDRB,wreg           ; PB0 controls the power supply
  304.    
  305.     ldi wreg,0x01
  306.     out PORTB,wreg          ; enable Power Supply
  307.    
  308.     out OCR1A,zero          ; clear output (keep PB1=0)
  309.                             ; maximum frequency OCR1B=0;
  310.                             ; period is OCR1B+1 * tclk
  311.     ldi wreg, 8             ; maximum length of PWM (for this clock) was 8
  312.     out OCR1B,wreg          ; this is arround 1us ~2 clocks per pixel
  313.    
  314.     ldi wreg, 0x63          ; PWM1,COM1A1,CS11,CS10 CK*4->T1
  315.     out TCCR1,wreg          ; PCK = 156.3ns, start timer
  316.    
  317.     ldi wreg, 0x20          ; Sleep Enable
  318.     out MCUCR,wreg
  319.    
  320.     ldi wreg,0x02           ; Enable TOIE0
  321.     out TIMSK,wreg         
  322.    
  323. ;unmutable variables
  324.     ldi wreg,0x04           ; ~650ns
  325.     mov SEND1,wreg
  326.     ldi wreg,0x01           ; ~300ns
  327.     mov SEND0,wreg
  328.     ret
  329.    
  330.  
  331. ;*********************************************************************************************
  332. ;* wr_frame
  333. ;*********************************************************************************************
  334. ; write a frame of neopixels (up to 16)
  335. ; copies data from GREEN1 to G1 ... RED0 to R0;
  336. ; uses G1,G0,B1,B0,R1,R0
  337.  
  338. wr_frame:
  339.     cli                     ; disable interrupts here
  340.     mov G1,GREEN1           ; copy the current to the working regs
  341.     mov G0,GREEN0
  342.     mov R1,RED1
  343.     mov R0,RED0
  344.     mov B1,BLUE1
  345.     mov B0,BLUE0            ; copy current frame to temp locations
  346.    
  347.     ldi led_cnt,num_leds    ; number of LEDs (max 16)
  348. gr_pix:
  349.     lsr G1                  ; [1] + 9
  350.     ror G0                  ; [1] rotate 16 bits, CY has bit
  351.     brcs gr_pix_s           ; [1/2]
  352.     mov wreg,SEND0          ; [1]
  353.     rjmp gr_wait            ; [2]
  354. gr_pix_s:
  355.     mov wreg,SEND1          ; [1] send a 1 for green
  356.     nop                     ; [1]
  357. gr_wait:
  358.     nop                     ; [1] 16
  359.     nop                     ; [1] 17
  360.     out OCR1A,wreg          ; [1] set bit to send
  361.    
  362. rd_pix:
  363.     lsr R1                  ; [1]
  364.     ror R0                  ; [1] rotate 16 bits, CY has bit
  365.     brcs rd_pix_s           ; [1/2]
  366.     mov wreg,SEND0          ; [1]
  367.     rjmp rd_wait            ; [2]
  368. rd_pix_s:
  369.     mov wreg,SEND1          ; [1] send a 1 for red
  370.     nop                     ; [1]
  371. rd_wait:
  372.     nop                     ; [1] 7 clocks
  373.     nop                     ; [1] 8 clocks
  374.     nop                     ; [1] 9 clocks
  375.     nop                     ; [1] 10 clocks
  376.     nop                     ; [1] 11 clocks
  377.     nop                     ; [1] 12 clocks
  378.     nop                     ; [1] 13 clocks
  379.     nop                     ; [1] 14 clocks
  380.     nop                     ; [1] 15 clocks
  381.     nop                     ; [1] 16 clocks
  382.     nop                     ; [1] 17 clocks
  383.     out OCR1A,wreg          ; [1] update
  384.    
  385. bl_pix:
  386.     lsr B1                  ; [1]
  387.     ror B0                  ; [1] rotate 16 bits, CY has bit
  388.     brcs bl_pix_s           ; [1/2]
  389.     mov wreg,SEND0          ; [1]
  390.     rjmp bl_wait            ; [2]
  391. bl_pix_s:
  392.     mov wreg,SEND1          ; [1] send a 1 for blue
  393.     nop                     ; [1]
  394. bl_wait:
  395.     nop                     ; [1] 7 clocks
  396.     nop                     ; [1] 8 clocks
  397.     nop                     ; [1] 9 clocks
  398.     nop                     ; [1] 10 clocks
  399.     nop                     ; [1] 11 clocks
  400.     nop                     ; [1] 12 clocks
  401.     nop                     ; [1] 13 clocks
  402.     nop                     ; [1] 14 clocks
  403.     nop                     ; [1] 15 clocks
  404.     nop                     ; [1] 16 clocks
  405.     nop                     ; [1] 17 clocks
  406.     out OCR1A,wreg          ; [1] update
  407.  
  408.     dec led_cnt             ; [1]
  409.     breq last               ; [1/2]
  410.     nop                     ; [1]
  411.     nop                     ; [1]
  412.     nop                     ; [1]
  413.     nop                     ; [1]
  414.     nop                     ; [1]
  415.  
  416.     rjmp gr_pix             ; [2]
  417.    
  418.    
  419. last:
  420.     nop                     ; [1]
  421.     nop                     ; [1]
  422.     nop                     ; [1]
  423.     nop                     ; [1]
  424.     nop                     ; [1]
  425.     nop                     ; [1]
  426.     nop                     ; [1]
  427.     nop                     ; [1]
  428.     nop                     ; [1]
  429.     nop                     ; [1]
  430.     nop                     ; [1]
  431.     nop                     ; [1]
  432.     nop                     ; [1]
  433.     nop                     ; [1] - 16 counts from last update
  434.     out OCR1A,zero          ; clear output
  435.     ret
  436.  
  437. ;*********************************************************************************************
  438. ;* wr_latch
  439. ;*********************************************************************************************
  440. ; make a break of 100-200ms (200 load T0 with 100)
  441. ; use timer 0 to count 200ms and sleep until interrup.
  442.  
  443. wr_latch:
  444.     sei                     ; enable interrupts
  445.  
  446.     ldi wreg,100
  447.     out TCNT0,wreg          ; reset timer0 (change for other timeout)
  448.  
  449.     ldi wreg,0x01           ; reset prescaller T0
  450.     out SFIOR,wreg
  451.    
  452.     ldi wreg,0x05           ; start T0, /1024
  453.     out TCCR0,wreg
  454.    
  455.     sleep                   ; wait for timeout
  456.     nop
  457.    
  458.     out TCCR0,zero          ; stop timer
  459.     cli                     ; disable interrupts
  460.    
  461.     ret
  462.    
  463. ;*********************************************************************************************
  464. ;* Random Number Generator
  465. ;*********************************************************************************************
  466. ; Pseudo Random Number generator, uses 32 bits (4 bytes) generator.
  467. ; if 32 bits (xor 32,22,2,1)
  468. ; 32,30,26,25
  469. ; if 16 bits (xor 16,15,13,4)
  470. ; Bit 1 in the taps is bit 1 of rnd_a (convention in lfsr).
  471. ; if operation is xor, all zeros blocks the lfsr, run randinit first
  472. ; if operation is xnor, all ones blocks the lfsr, adapt randinit then run it first.
  473. ; CY returns a pseudo-random bit sequence; rnd_a to rnd_d hold a pseudo random sequence
  474. ; of values
  475. ;*********************************************************************************************
  476. #define MASK_A  0b00000000          /* constants to separate the bits, anded with rnd_a */
  477. #define MASK_B  0b00000000          /* constants to separate the bits, anded with rnd_b */
  478. #define MASK_C  0b00000000          /* constants to separate the bits, anded with rnd_c */
  479. #define MASK_D  0b10100011          /* constants to separate the bits, anded with rnd_d */
  480. random:
  481.     clr rnd_xor                     ;clear xor accumulative register
  482.     ldi wreg,MASK_D
  483.     and wreg,rnd_d
  484.     eor rnd_xor,wreg
  485.     ldi wreg,MASK_C
  486.     and wreg,rnd_c
  487.     eor rnd_xor,wreg
  488.     ldi wreg,MASK_B
  489.     and wreg,rnd_b
  490.     eor rnd_xor,wreg
  491.     ldi wreg,MASK_A
  492.     and wreg,rnd_a                  ; load mask and extract bits from register
  493.     eor rnd_xor,wreg                ; xor with accumaltive
  494.     clr wreg                        ; counter of ones
  495. rand_lp:
  496.     lsr rnd_xor                     ; Rotate to bit to carry
  497.     brcc rand_nx                    ; carry clear skip
  498.     inc wreg
  499. rand_nx:
  500.     tst rnd_xor                     ; stop when no more ones to count
  501.                                     ; it is a bound operation, zeros are shift in so max is 8 shifts (bit7=1)
  502.     brne rand_lp                    ; repeat if !=
  503.                                     ; CY holds a bit of a pseudo random sequence
  504.     lsr wreg                        ; if odd number of bits, wreg()==1 => XOR operation
  505.     rol rnd_a                       ; feed CY in shift register
  506.     rol rnd_b
  507.     rol rnd_c
  508.     rol rnd_d
  509.     mov wreg,rnd_a                  ;copy shifted bit to CY and return
  510.     lsr wreg
  511.     ret
  512. ;*********************************************************************************************
  513. ; Because a XOR (XNOR) is made of selected bits, one value of the random value can block it.
  514. ; tests for a  (FFFF) and changes the value to the opposite.
  515. rnd_init:
  516.     clr wreg
  517.     or wreg,rnd_a
  518.     or wreg,rnd_b
  519.     or wreg,rnd_c
  520.     or wreg,rnd_d
  521.     breq rnd_init0
  522.     ret
  523. rnd_init0:
  524.     ldi wreg,0x55
  525.     mov rnd_a,wreg
  526.     mov rnd_b,wreg
  527.     mov rnd_c,wreg
  528.     mov rnd_d,wreg
  529.     ret
  530. ;*********************************************************************************************
  531.    
  532.    
  533. .section .eeprom
  534.     .org 0x00
  535.     .ds 1                           ; holds calibration byte
  536. .end
RAW Paste Data
Top