lampe.asm


1
.include "tn12def.inc"
2
3
.equ  initialgotospeed=$40
4
.equ  normalgotospeed  =$10
5
.equ  fastgotospeed  =$08
6
.equ  veryfastgotospeed  =$04
7
.equ  dotspeed  =$20
8
.equ  dashspeed  =$e0
9
.equ  pausespeed  =dotspeed
10
.equ  outputpin  =4
11
.equ  lobatpin  =3
12
.equ  buttonpin  =0
13
14
.equ  maxtastverh  =100
15
.equ  maxpower  =100
16
.equ  highpower  =84  ; dim to 70% light - i.e. 84% power
17
.equ  medpower  =63  ; dim to 40% light - i.e. 63% power
18
.equ  lowpower  =31  ; dim to 10% light - i.e. 31% power
19
.equ  lowbatpower  =15  ; when at lobat dim to minimal power
20
        ; consumption, but enough for reading
21
        ; instruments.
22
.equ  nopower    =0  ; lamp off
23
24
.def  gotospeed=r18
25
.def  lobat  =r19
26
.def  gdelay  =r20
27
.def  gdelay2  =r21
28
.def  gdelay3  =r23
29
.def  newtastverh=r24
30
.def  tastmax =r25
31
.def  tastverh=r26
32
.def  ison  =r27
33
.def  portbsh  =r28
34
.def  temp  =r29
35
.def  itemp  =r30
36
37
.ORG $000
38
  rjmp RESET
39
.ORG $001
40
  rjmp EXT_INT0
41
.ORG $002
42
  rjmp PIN_CHANGE
43
.ORG $003
44
  rjmp TIM0_OVP
45
.ORG $005
46
  rjmp ANA_CMP
47
48
shortdelaysub:
49
  clr     gdelay
50
sdm2:  DEC  gdelay
51
  BRNE    sdm2
52
sdm3:  DEC gdelay
53
  BRNE  sdm3
54
sdm4:  DEC gdelay
55
  BRNE  sdm4
56
  ret
57
;
58
; A simple macro for generating a short delay. 
59
; This is used for blinking SOS
60
;
61
.macro  shortdelay
62
.if 1 = 0
63
  clr  gdelay
64
sdm2:  DEC gdelay
65
  BRNE  sdm2
66
sdm3:  DEC gdelay
67
  BRNE  sdm3
68
sdm4:  DEC gdelay
69
  BRNE  sdm4
70
.else
71
  RCALL shortdelaysub
72
.endif
73
.endmacro
74
75
;
76
; Delay for as long as a "dot" symbol should be on.
77
;
78
.macro  dotdelay
79
  ldi     gdelay2,dotspeed
80
dd2:  shortdelay
81
  dec  gdelay2
82
  brne  dd2
83
.endmacro
84
85
;
86
; Delay for as long as a "dash" symbol should be on.
87
;
88
.macro  dashdelay
89
  ldi     gdelay2,dashspeed
90
dad2:  shortdelay
91
  dec  gdelay2
92
  brne  dad2
93
.endmacro
94
95
;
96
; Delay for as long as a pause between symbols should be.
97
;
98
.macro  pausedelay
99
  ldi     gdelay2,pausespeed
100
pd2:  shortdelay
101
  dec  gdelay2
102
  brne  pd2
103
.endmacro
104
105
;
106
; Send a dot with the inter-symbol pause trailing
107
;
108
.macro saydot
109
  ldi newtastverh,maxpower
110
  rcall soft_goto
111
  dotdelay
112
  ldi newtastverh,nopower
113
  rcall soft_goto
114
  pausedelay
115
.endmacro
116
117
;
118
; Send a dash with the inter-symbol pause trailing
119
;
120
.macro saydash
121
  ldi newtastverh,maxpower
122
  rcall soft_goto
123
  dashdelay
124
  ldi newtastverh,nopower
125
  rcall soft_goto
126
  pausedelay
127
.endmacro
128
129
;
130
; Delay for a inter-character pause - minus the already done inter-symbol pause
131
;
132
.macro newchardelay
133
  pausedelay
134
.endmacro
135
136
;
137
; Send an s, including trailing inter-char pause
138
;
139
.macro says
140
  saydot
141
  saydot
142
  saydot
143
  newchardelay
144
.endmacro
145
146
;
147
; Send an o, including trailing inter-char pause
148
;
149
.macro sayo
150
  saydash
151
  saydash
152
  saydash
153
  newchardelay
154
.endmacro
155
156
;
157
; Send an a, including trailing inter-char pause
158
;
159
.macro saya
160
  saydot
161
  saydash
162
  newchardelay
163
.endmacro
164
165
;
166
; Send an e, including trailing inter-char pause
167
;
168
.macro saye
169
  saydot
170
  newchardelay
171
.endmacro
172
173
TIM0_OVP:
174
  cpi ison,$00
175
  breq IS_OFF
176
  ldi ison,$00
177
  ldi itemp,$00
178
  SUB itemp,tastverh
179
  breq justret
180
  out TCNT0,itemp
181
  sbi PORTB,outputpin
182
justret:
183
  reti
184
IS_OFF:
185
  ldi ison,$ff
186
  ldi itemp,$00
187
  sub itemp,tastmax
188
  add itemp,tastverh
189
  breq justret
190
  cbi PORTB,outputpin
191
  out TCNT0,itemp
192
  reti
193
194
EXT_INT0:
195
  reti
196
197
PIN_CHANGE:
198
  reti
199
200
;
201
; The analog comparator triggered. This means we have a lobat condition
202
; 
203
ANA_CMP:
204
  SBIC ACSR,5
205
  rjmp on_lobat
206
have_enough:
207
  cbi PORTB,lobatpin
208
  reti
209
on_lobat:
210
  ser lobat
211
  sbi PORTB,lobatpin
212
  reti
213
214
set_lobat:
215
  ser lobat
216
  sbi PORTB,lobatpin
217
  ret
218
219
reset_lobat:
220
  clr lobat
221
  cbi PORTB,lobatpin
222
  ret
223
224
225
soft_goto:
226
  cp tastverh,newtastverh
227
  breq sg_doret
228
  brlo goto_less
229
  dec tastverh
230
  rjmp redo_goto
231
sg_doret:
232
  ret
233
goto_less:
234
  inc tastverh
235
redo_goto:
236
  mov  gdelay2,gotospeed
237
rg2:  clr     gdelay
238
rg1:  dec  gdelay
239
  brne  rg1
240
  dec  gdelay2
241
  brne  rg2
242
  rjmp soft_goto
243
244
245
;
246
; Wait for key. A looong keypress (about 6 seconds) enters SOS-Mode
247
;
248
249
.macro sostimingdelay
250
  ldi gdelay3,$15
251
down:
252
  dec gdelay3
253
  brne down
254
.endmacro
255
256
waitforkey:
257
  CLR gdelay2
258
  CLR gdelay
259
wfk_loop:
260
  sostimingdelay
261
  dec gdelay
262
  BRNE skipdec2
263
  dec gdelay2
264
  BREQ have_sos    ; YEAH - we really jump into something
265
        ; that doesn't return. SOS-Mode can only
266
        ; be left by a RESET.
267
skipdec2:
268
  SBRC lobat,0    ; lobat clear?
269
  ret      ; if lobat is set, break out
270
  SBIS PINB,buttonpin  ; if Button is not pressed, skip to waitforkey2
271
  rjmp wfk_loop    ; if Button is pressed, keep looping
272
waitforkey2:
273
  SBRC lobat,0    ; lobat clear?
274
  ret      ; if lobat is set, break out
275
  SBIC PINB,buttonpin  ; if Button is pressed, ret
276
  rjmp waitforkey2  ; if Button is not pressed, keep looping
277
  ret  
278
279
280
waitforkey_nolobatbreak:
281
  CLR gdelay2
282
  CLR gdelay
283
wfk_loop_nlbb:
284
  sostimingdelay
285
  dec gdelay
286
  BRNE skipdec3
287
  dec gdelay2
288
  BREQ have_sos    ; YEAH - we really jump into something
289
        ; that doesn't return. SOS-Mode can only
290
        ; be left by a RESET.
291
skipdec3:
292
  SBIS PINB,buttonpin  ; if Button is not pressed, skip to waitforkey2
293
  rjmp wfk_loop_nlbb  ; if Button is pressed, keep looping
294
waitforkey_nlbb2:
295
  SBIC PINB,buttonpin  ; if Button is pressed, ret
296
  rjmp waitforkey_nlbb2  ; if Button is not pressed, keep looping
297
  ret  
298
299
;
300
; Blink SOS
301
;
302
; In this mode we don't give a f*** about the battery life
303
;
304
have_sos:
305
  ldi gotospeed,veryfastgotospeed
306
  says      ; Blink ... --- ...
307
  sayo
308
  says
309
  ldi temp,65    ; Wait about 10 seconds
310
sos_delay:
311
  pausedelay
312
  dec temp
313
  brne sos_delay
314
  rjmp have_sos
315
316
; *************************************************************************
317
; Main program starts here
318
; *************************************************************************
319
320
RESET:
321
;
322
; Initialize Variables
323
;
324
  CLR ison
325
  ldi tastverh,nopower
326
  LDI tastmax,maxtastverh
327
;
328
; Setup the Output pins
329
;
330
  LDI temp,(1<<outputpin)|(1<<lobatpin)
331
  OUT DDRB,temp
332
  ; activate pullup resistor on the
333
  ; pin the button is connected to
334
  LDI temp,(1<<buttonpin)  
335
  OUT PORTB,temp
336
337
;
338
; Set up the timer/counter.
339
; ATTiny12 has an internal 1.2MHz clock.
340
; That makes for 18750Hz at CK/64.
341
; Using an 8 Bit counter, we can thus reach Frequencies between
342
; 73Hz and 18kHz for driving the lamp.
343
; For ease of calculation I chose 187Hz (tastmax=100).
344
;
345
  LDI temp,$03  ;  CK/64
346
  OUT TCCR0,temp
347
;
348
; Enable timer interrupt.
349
;
350
  LDI temp,$02
351
  OUT TIMSK,temp
352
  SEI
353
354
;
355
; Now enable the analog comparator stuff. 
356
;
357
  LDI temp,$48  ; $40=enable bandgap $08=Interrupt enable 
358
      ; $00=int on toggle.
359
  OUT ACSR,temp
360
; The manual says not to do this, as it can cause interrupts while bits
361
; are being shuffled.
362
; As we are only setting a flag in the interrupt, which gets cleared after
363
; startup anyway - we don't care.
364
365
366
softstart:
367
;
368
; Do a soft start of the lamp. Then reset the lobat entry.
369
; This is done at startup in order to reset any pending lobat 
370
; interrupts.
371
; We check the button condition.
372
; If the lamp comes up with the button active, either the button is 
373
; stuck, or the user is requesting "emergency full power".
374
; As a safe default, we keep the lamp at 100% if that happens.
375
;
376
377
  ldi gotospeed,initialgotospeed
378
  ldi newtastverh,lowpower
379
  rcall soft_goto;
380
381
  ldi gotospeed,normalgotospeed
382
  ldi newtastverh,maxpower
383
  rcall soft_goto;
384
385
  rcall reset_lobat
386
387
  SBIS PINB,buttonpin  ; if Button is not pressed, skip emergency mode
388
  rjmp emergency_full
389
  
390
;
391
; If we started up in alobat situation and are not in emergency mode,
392
; jump directly to lobat.
393
;
394
  SBIC ACSR,5    ; Is the AC output clear? Then all is well.
395
  rjmp have_lobat    ; otherwise indicate lobat.
396
  rjmp ss2
397
398
;
399
; usually we come back here. The lamp starts up soft as well,
400
; but we assume lobat has been cleared before.
401
; Notice, that detecting lobat is an edge-triggered action.
402
; So if we are on lobat here, and lobat flag has been cleared,
403
; we are toast.
404
;
405
406
;
407
; While in normal operating mode, we wait for button press. 
408
; the button press fuction will also return, if a lobat condition
409
; is detected. This macro will jump to "have_lobat", if lobat
410
; condition is active.
411
;
412
.macro testandjumplobat
413
  tst  lobat
414
  brne  have_lobat
415
.endmacro
416
417
.macro waitforkey_and_lobat
418
  rcall waitforkey
419
  testandjumplobat
420
.endmacro
421
422
softstart2:
423
  ldi newtastverh,maxpower
424
  rcall soft_goto;
425
426
ss2:
427
  waitforkey_and_lobat
428
429
; dim to high power setting
430
431
  ldi newtastverh,highpower
432
  rcall soft_goto;
433
  waitforkey_and_lobat
434
435
; dim to medium power setting
436
437
  ldi newtastverh,medpower
438
  rcall soft_goto
439
  waitforkey_and_lobat
440
441
lopower:
442
; dim to low power setting
443
444
  ldi newtastverh,lowpower
445
  rcall soft_goto
446
  waitforkey_and_lobat
447
448
; dim to medium power setting
449
450
  ldi newtastverh,medpower
451
  rcall soft_goto;
452
  waitforkey_and_lobat
453
  
454
; dim to high power setting
455
456
  ldi newtastverh,highpower
457
  rcall soft_goto;
458
  waitforkey_and_lobat
459
460
; jump to start - brings us back to 100%
461
  rjmp softstart2
462
463
464
;
465
; We have a lobat condition. 
466
; First notify the user by morsing A A A (like Attention Accu Alert)
467
; then dim the light to 20% Power, which probably gives about 4% Light.
468
;
469
have_lobat:
470
  rcall set_lobat  ; reset the lobat condition.
471
  ldi newtastverh,lowbatpower
472
  rcall soft_goto    ; bring us to minimum light.
473
  ldi gotospeed,fastgotospeed
474
  saya
475
  ldi gotospeed,normalgotospeed
476
  ldi newtastverh,lowbatpower
477
  rcall soft_goto    ; bring us to minimum light.
478
  rcall waitforkey_nolobatbreak
479
        ; if the user presses a button, he wants
480
        ; more light.
481
  rcall reset_lobat  ; reset the lobat condition.
482
  SBIC ACSR,5    ; Is the AC output clear? In that case we 
483
        ; might have enough power for a higher
484
        ; setting.
485
  rjmp have_lobat    ; otherwise indicate lobat.
486
  rjmp lopower    ; give him lopower first.
487
488
emergency_full:
489
  ldi newtastverh,nopower
490
  rcall soft_goto    ; bring us to minimum light.
491
  ldi newtastverh,maxpower
492
  rcall soft_goto    ; bring us to minimum light.
493
forever:
494
  rjmp forever