document.write('
Data hosted with ♥ by Pastebin.com - Download Raw - See Original
  1. ;***************************************************************************
  2. ;* Title            : SolarLight
  3. ;* Version          : rev. 2.1
  4. ;* Last updated         : 2009.12.11
  5. ;* Target           : ATTiny15L @ 1.6MHz (internal osc)
  6. ;* DESCRIPTION          :
  7. ;***************************************************************************
  8. ;*
  9. ;* Code Control
  10. ;*
  11.     .nolist
  12.     .include "tn15def.inc"      ; Import Register definitions
  13.     .list
  14. ;*
  15. ;* DEBUG CONTROL VARIABLES
  16. ;*
  17. ;   .def DEBUG      = R29   ; debug control variable
  18. ;   .def DB_CNT     = R28   ; debug help variable
  19.  
  20. ;*
  21. ;* Equates
  22. ;*
  23. ; ATTiny15L         PinNb   Prototype
  24. ; RESET/ADC0            - 1 -   RST
  25. ; PortB4/ADC3(*)        - 2 -   Vsun
  26. ; PortB3/ADC2(*)        - 3 -   Vled
  27. ;               - 4 -   GND
  28. ; PortB0/AIN0/AREF      - 5 -   Status LED
  29. ; PortB1/AIN1/OC1A      - 6 -   MOSFET output
  30. ; PortB2/ADC1/T0/INT0       - 7 -   Vbat
  31. ;               - 8 -   VCC
  32. ;(*) change in ATTiny25/45/85
  33.  
  34. ; FCLK WATCHDOG = 350kHz @ Vcc=3V;
  35. ; FCLK WATCHDOG = 500kHz @ Vcc=3.5V (* arround this value)
  36. ; FCLK WATCHDOG = 700kHz @ Vcc=4V
  37.     .equ    CNT_CHRG    =3600   ; at least 1 hour of charging
  38.  
  39.     .equ    VCHRG       =200/20 ; 200mV if (Vf(diode)> 200mV) => charging
  40.     .equ    VBATMIN     =3000/20; 3000mV
  41.     .equ    VSUNMIN     =3000/20; 3000mV
  42.     .equ    VLEDMAX     =4750/20; 4700mV i.e. no LED! or Overcurrent
  43.     .equ    VLEDREF     =3200/20; Vf=3720mV@1A (3200mV@700mA simulation tests)
  44.    
  45.     .equ    PWMMAX      =166    ; maximum allowable duty cycle =0.60
  46.     .equ    PWMREF      =145    ; reference duty cycle =0.57
  47.     .equ    PWMMIN      =100    ; minimum allowable duty cycle =0.39
  48.  
  49. ;*
  50. ;* Definitions
  51. ;*
  52.     .def zero       =R0 ; register holding zero (after oscillator calibration!)
  53.     .def one        =R1
  54.     .def mcusr_sv       =R3 ; save MCUSR for later testing
  55.  
  56.     .def chrg_cntl      =R7 ; charging counter low
  57.     .def chrg_cnth      =R8 ; charging counter high
  58.  
  59.     .def accl       =R16    ; accumulator low/temporary holding variable
  60.     .def acch       =R17    ; accumulator high/temporary holding variable
  61.     .def vsun       =R18    ; result of conversion Vsolarpanel
  62.     .def vbat       =R19    ; result of conversion Vbattery
  63.     .def vled       =R20    ; result of conversion VLED
  64.     .def pwm        =R21    ; next pwm value
  65. ;*
  66. ;* Code
  67. ;*
  68.     .cseg
  69.     .org 0
  70.     rjmp    RESET           ; RESET handle
  71.     reti                ; INT0
  72.     reti                ; PCI0
  73.     reti                ; OC1
  74.     reti                ; OVF1
  75.     reti                ; OVF0
  76.     reti                ; ERDY
  77.     reti                ; ACI
  78.     reti                ; ADCC
  79. ;*
  80. ;* Main
  81. ;*
  82. RESET:
  83.     wdr             ; WDT reset - just to be sure !
  84.     ldi accl,0b00011111
  85.     out WDTCR,accl
  86.     ldi accl,0b00010111
  87.     out WDTCR,accl          ; WDT disabled
  88.     in mcusr_sv,MCUSR       ; save MCUSR for test of watchdog timer reset
  89.     sbrc mcusr_sv,WDRF      ; skip if not wdt reset (power up)
  90.     rjmp INIT           ; jump if watchdog reset
  91.     rcall chrg_ld           ; reset counter of charging times
  92. INIT:
  93.     ldi ZH,high(FLASHEND<<1)
  94.     ldi ZL,low((FLASHEND<<1)+1) ; get OSCCAL value
  95.     lpm             ; read from ROM(Z)->R0
  96.     out OSCCAL,zero         ; set oscillator calibration
  97.  
  98.     clr zero            ; setup zero register (lpm destroys zero reg!!)
  99.     out MCUSR,zero          ; clear MCUSR
  100.  
  101.     out PORTB,zero          ; clear output port
  102.     ldi accl,0b0000_0010        ; Bit 0 as input (check if LED is tied to VCC => allways on)
  103.     out DDRB,accl           ; set LED as input, MOSFET GATE as output.
  104.  
  105.     sbic PINB,PORTB0        ; skip if not connected to VCC
  106.     rjmp LIGHT_001
  107.  
  108.     ldi accl,0b0000_0011
  109.     out DDRB,accl           ; set status LED/MOSFET GATE as outputs
  110.  
  111. BEGIN:
  112.     rcall sample            ; sample light values
  113.     mov accl,vsun           ; check if charging Vsun > Vbat+.1V
  114.     sub accl,vbat           ; accl = vsun-vbat
  115.     brmi BEGIN_000          ; difference negative (vbat>vsun)
  116.     cpi accl,VCHRG          ; compare difference with diode drop
  117.     brlo BEGIN_000          ; Negative ?
  118.     rcall chrg_dec          ; decrement charging counter
  119.     rjmp deep_sleep         ; goto sleep unit WDT
  120. BEGIN_000: 
  121.     mov accl,chrg_cntl
  122.     or accl,chrg_cnth       ; test charge time for zero, return with Z set
  123.     breq BEGIN_001          ; if counter == 0 do other checks
  124.     rjmp deep_sleep         ; else deep sleep
  125. BEGIN_001:
  126.     rcall chrg_ld           ; reload counter
  127. LIGHT:
  128.     cpi vbat,VBATMIN        ; check if enough battery 3.0V
  129.     brsh LIGHT_000          ; jump if >=
  130.     rjmp deep_sleep         ; wait another counter period
  131. LIGHT_000:         
  132.     cpi vsun,VSUNMIN        ; check if Vsun above 3.5V
  133.     brlo LIGHT_001          ; light on if lower
  134.     rjmp deep_sleep         ; else deep sleep
  135. LIGHT_001:
  136.     ldi accl,0b0110_0010        ; PWM mode, non inverted PWM,PCK/2
  137.     out TCCR1,accl
  138.     ser accl
  139.     out OCR1B,accl          ; set OCR1B=0hFF, PWM frequency 50KHz
  140.     ldi accl,PWMREF
  141.     out OCR1A,accl          ; reference duty cycle
  142.     mov pwm,accl            ; set pwm
  143. LIGHT_ON:
  144.     rcall sample            ; sample analog values
  145.  
  146.     cpi vbat,VBATMIN        ; if vbatt < vbatt min
  147.     brlo deep_sleep
  148.     cpi vsun,VSUNMIN        ; if Vsun > vsun min , sun shinning
  149.     brsh deep_sleep
  150.     cpi vled,VLEDMAX        ; if Vled > vled max
  151.     brsh deep_sleep         ; shutdown !!
  152.                     ; adjusting pwm
  153.     cpi vled,VLEDREF
  154.     breq LIGHT_ON           ; branch if vled == VLEDREF ...stable just continue...
  155.     brsh LIGHT_ON_000       ; branch if vled >= VLEDREF
  156.  
  157.     cpi pwm,PWMMAX             
  158.     brsh LIGHT_ON_001       ; branch if pwm >= PWMMAX
  159.     inc pwm
  160.     rjmp LIGHT_ON_001
  161.  
  162. LIGHT_ON_000:
  163.     cpi pwm,PWMMIN
  164.     brlo LIGHT_ON_001       ; branch if pwm < PWMMIN
  165.     dec pwm
  166. LIGHT_ON_001:
  167.     out OCR1A,pwm           ; update pwm register
  168.     rjmp LIGHT_ON           ; loop
  169.  
  170. ;*
  171. ;* Functions
  172. ;*
  173. ;* Function         : Sample
  174. ;* Description          : sample 3 analog inputs, store MSB of conversion in registers
  175. ;*              : use only 8 bits of the conversion for reduced complexity
  176. ;*              : Value = Vin*(10/(10+10))/(2.56/256)
  177. ;*              : 1LSB = 20mV
  178. ;* Code Size            : 22 Words
  179. ;* Cycles           : 108 + conversion time!
  180. ;* Low Register Usage       : R4,R5,R6 (results of conversion)
  181. ;* High Register Usage      : R16 (acc)
  182. ;* Interrupt Usage      : None
  183. ;* Notes: all conversions are extended (change of channel) according to datasheet pg 45
  184. ;* sample and hold is 13.5 cy, total conversion in 25 cy. currently ADC clock is CK/128,
  185. ;* could be changed for system stability to CK/2,CK/4|8|16|32|64|128 in ADCSR (0bxxxx_x000,010,011,100,101,110,111)
  186. ;* current setting CK/128 ADCSR =0bxxxx_x111.
  187. ;*
  188. sample:
  189.     sbi PORTB,PORTB0
  190.     ldi accl,0b1010_0001        ; select PB2/Vbat, ADLAR=1 (Left justified), Vref=2.56V
  191.     out ADMUX,accl
  192.     ldi accl,0b1100_0111        ; Enable, Start conversion, CK/128 *
  193.     out ADCSR,accl
  194. smpl_000:
  195.     sbic ADCSR,ADSC         ; wait for end of conversion
  196.     rjmp smpl_000          
  197.     in vbat,ADCH            ; store conversion result
  198.  
  199.     ldi accl,0b1010_0010        ; select PB3/Vled, ADLAR=1 (Left justified), Vref=2.56V
  200.     out ADMUX,accl
  201.     ldi accl,0b1100_0111        ; Enable, Start conversion, CK/128 *
  202.     out ADCSR,accl
  203. smpl_001:
  204.     sbic ADCSR,ADSC         ; wait for end of conversion
  205.     rjmp smpl_001          
  206.     in vled,ADCH            ; store conversion result
  207.  
  208.     ldi accl,0b1010_0011        ; select PB4/Vsun, ADLAR=1 (Left justified), Vref=2.56V
  209.     out ADMUX,accl
  210.     ldi accl,0b1100_0111        ; Enable, Start conversion, CK/128 *
  211.     out ADCSR,accl
  212. smpl_002:
  213.     sbic ADCSR,ADSC         ; wait for end of conversion
  214.     rjmp smpl_002          
  215.     in vsun,ADCH            ; store conversion result
  216.     cbi PORTB,PORTB0
  217.     ret
  218. ;* Function         : Charge Counter Load
  219. ;* Description          : Load counter with reload value
  220. ;* Code Size            : 5 Words
  221. ;* Low Register Usage       : R7,R8 (Charge counter)
  222. ;* High Register Usage      : R16 (accl)
  223. ;* Interrupt Usage      : None
  224. chrg_ld:
  225.     ldi accl,high(CNT_CHRG)     ; if power on reset
  226.     mov chrg_cnth,accl
  227.     ldi accl,low(CNT_CHRG)      ; load charging counter
  228.     mov chrg_cntl,accl
  229.     ret
  230.  
  231. ;* Function         : Charge decrement / Zero?
  232. ;* Description          : decrement counter (if > 0), Z set if Zero
  233. ;* Code Size            : 12 Words
  234. ;* Low Register Usage       : R7,R8 (Charge counter)
  235. ;* High Register Usage      : R16 (accl)
  236. ;* Interrupt Usage      : None
  237. chrg_dec:
  238.     mov accl,chrg_cntl
  239.     or accl,chrg_cnth       ; test for zero, return with Z set
  240.     brne chrg_dec_000       ; skip return if non zero
  241.     ret             ; with Z set
  242. chrg_dec_000:
  243.     mov accl,chrg_cntl
  244.     subi accl,1
  245.     mov chrg_cntl,accl      ; counterL - 1
  246.     brcs chrg_dec_001       ; adjust counterH if carry
  247.     ret             ; return if no carry
  248. chrg_dec_001:
  249.     dec chrg_cnth
  250.     clz             ; just in case dec counter H was zero
  251.     ret
  252.  
  253. ;* Function         : Deep Sleep
  254. ;* Description          :
  255. ;* Code Size            :  Words
  256. ;* Low Register Usage       :
  257. ;* High Register Usage      :
  258. ;* Interrupt Usage      : None
  259. deep_sleep:
  260.     out TCCR1,zero          ; stop timer
  261.     out PORTB,zero          ; clear all outputs
  262.     out ADCSR,zero          ; power off ADC
  263.     ldi accl,0b0000_1111        ; WDT EN, 2048K
  264.     out WDTCR,accl          ; start watchdog timer and wait 4 seconds
  265.     ldi accl,0b0011_0000        ; Sleep enable, Power Down
  266.     out MCUCR,accl
  267.     wdr
  268.     sleep
  269. deep_sleep_000:
  270.     rjmp deep_sleep_000
  271.  
  272. ;***** DEBUG *****
  273. .IFDEF DEBUG
  274. ;* Function         : DEBUG OUTPUT
  275. ;* Description          : outputs in the LED pin 1 byte coded as FM clock+data(0,1) MSB first
  276. ;* Code Size            : 25 Words
  277. ;* Low Register Usage       : None
  278. ;* High Register Usage      : R29,R28
  279. ;* Interrupt Usage      : None
  280. dbug:
  281.     ldi DB_CNT,8            ; output 8 bits [1]
  282.     sbi DDRB,PORTB0         ; always do it [2]
  283.     sbi PORTB,PORTB0        ; start bit longer than normal 1 [2]
  284.     nop
  285.     nop
  286.     nop
  287.     nop
  288.     cbi PORTB,PORTB0        ; short break, begin of data [2]
  289. dbug_000:
  290.     rol DEBUG           ; bit7 -> C [1]
  291.     brcc dbug_001           ; branch if C=0 [2] non taken [1]
  292.     sbi PORTB,PORTB0        ; send a one [2]
  293.     cbi PORTB,PORTB0
  294.     sbi PORTB,PORTB0        ; send a one [2]
  295.     cbi PORTB,PORTB0
  296.     rjmp dbug_002           ; [2]
  297. dbug_001:
  298.     sbi PORTB,PORTB0        ; send a one [2]
  299.     cbi PORTB,PORTB0
  300.     nop
  301.     nop
  302.     nop
  303.     nop
  304.     nop
  305. dbug_002:
  306.     dec DB_CNT          ; [1]
  307.     brne dbug_000           ; [1] false, [2] taken
  308.     ret
  309. .ENDIF
  310. ;***** DEBUG *****
');