summaryrefslogtreecommitdiff
path: root/Fernbedienung.asm
blob: c0b3ae8d4319c228eefffeeb8644d424db1fe5c0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
/*
 * Fernbedienung.asm
 *
 *  Created: 08.10.2015 14:35:11
 *   Author: Erich
 */ 


.DEF sbuff0 = r0		; serieller Puffer 0 bis
.DEF sbuff1 = r1
.DEF sbuff2 = r2
.DEF sbuff3 = r3
.DEF sbuff4 = r4		; 4
.DEF lastB = r5			; letzter Zustand von PINB
.DEF lt1p0l = r6		; letzte Flankenposition PINB0 (Timer 1) low
.DEF lt1p0h = r7		; dito high
.DEF lt1p1l = r8		; dito PINB1 low
.DEF lt1p1h = r9		; dito high
.DEF bcnt0 = r10		; Bitzähler PINB0
.DEF bcnt1 = r11		; Bitzähler PINB1
.DEF t1moml = r12		; momentane Position Timer 1 low
.DEF t1momh = r13		; dito high
.DEF aender = r14		; Änderungen in PINB

 	rjmp	RESET
	reti
	reti
	reti
	reti
	reti
	reti
	reti
	reti
	rjmp TIMER0COMPA				; Timer0 Compare Match A
	reti
	reti
	reti
	reti
	reti
	reti
	reti

 RESET:
	ldi r16,low(RAMEND)				; Stackpointer initialisieren
	out SPL,r16

	ldi r16,0x80
	out CLKPR,r16
	ldi r16,0x00
	out CLKPR,r16					; System-Vorteiler auf 1

	ldi r16,0x03
	out PRR,r16						; Clocks: Timer/Counter 1 an, Timer/Counter 0 an, USI aus, ADC aus ... zum Stromsparen
	ldi r16,0x00
	out WDTCSR,r16					; Watchdog aus

	ldi r16,0x02
	out PORTA,r16					; 6x n.d., PORTA1 high (RS232-Sender), kein Pull-up an PORTA0 (RS232-Empfänger)
	ldi r16,0x00
	out PORTB,r16					; 2x n.d., kein Pull-up an PORTB1 (IR-Empfänger 1) & PORTB0 (IR-Empfänger 0)
	ldi r16,0x06
	out DDRA,r16					; Ausgänge: PORTA1 (RS232-Sender), PORTA2 (Test)
	ldi r16,0x00
	out DDRB,r16					; keine Ausgänge auf PORTB

	ldi r16,0x02					; Timer0 Compare-Match-A Interrupt an
	out TIMSK0,r16

	ldi r16,104
	out OCR0A,r16
	ldi r16,0x02					; CTC-Modus: Periode = OCR0A = 104 -> 9600 baud
	out TCCR0A,r16
	ldi r16,0x02					; Vorteiler 8 für Timer 0
	out TCCR0B,r16

	ldi r16,0x02					; Vorteiler 8 für Timer 1
	out TCCR1B,r16

	ldi r16,0x21					; Start-Bit und
	mov sbuff0,r16
	ldi r16,0x15					; 0x48 ('H') und Start-Bit und
	mov sbuff1,r16
	ldi r16,0x56					; 0x61 ('a') und Start-Bit und
	mov sbuff2,r16
	ldi r16,0x48					; 0x21 ('!') und Start-Bit
	mov sbuff3,r16
	ldi r16,0x0d					; und 0x0d (CR)
	mov sbuff4,r16

	in lt1p0l,TCNT1L
	in lt1p0h,TCNT1H
	movw lt1p1l,lt1p0l

	in lastB,PINB
	ldi r16,0x03
	and lastB,r16

	sei

MAINLOOP:
	in r16,PINB

	andi r16,0x03
	eor r16,lastB
	breq MAINLOOP					; keine Änderung

	eor lastB,r16					; Änderung übernehmen
	mov aender,r16					; Änderungen merken

	in t1moml,TCNT1L
	in t1momh,TCNT1H				; Zählerstand holen
	movw r16,t1moml					; und kopieren

	sbrs aender,0
	rjmp PIN0WACKELTNICHT

	sub r16,lt1p0l
	sbc r17,lt1p0h					; r17:r16 = TimeDiff

	movw lt1p0l,t1moml				; aktuellen Zählerstand als alten setzen

	subi r16,0xb1
	sbci r17,0x01					; - 865/2 = 0x01b1 = halbes Bit

	brcs RESET0						; zu kurzes Bit -> Fehler!

	subi r16,0x61
	sbci r17,0x03					; - 865   = 0x0361 = kurzes Bit
	brcc KEINKURZESBIT0
	
	clr r16							; wird einfach gespeichert!
	inc bcnt0
	rjmp WEITER0
KEINKURZESBIT0:
	subi r16,0x61
	sbci r17,0x03					; - 865   = 0x0361 = (noch ein) kurzes Bit (= langes Bit)
	brcc RESET0						; zu langes Bit -> Fehler

	inc bcnt0
	inc bcnt0
	ldi r16,0x01					; wird doppelt gespeichert!

WEITER0:
	clc
	sbrs lastB,0					; alten Pinzustand
	sec								; nach C
	lds r17,(0x0060)				; das erste der insgesamt vier Bytes von empfangenen Bits
	rol	r17
	sts (0x0060),r17
	lds r17,(0x0061)
	rol r17
	sts (0x0061),r17
	lds r17,(0x0062)
	rol r17
	sts (0x0062),r17
	lds r17,(0x0063)
	rol r17
	sts (0x0063),r17
	brcs RESET0						; es kamen mehr als 32 Bits an -> Fehler!

	subi r16,0x01
	brcc WEITER0

	ldi r16,0x1a
	cp bcnt0,r16

	brcs ENDE0						; noch keine 26 klein-Bits angekommen -> Ende

	ldi r16,0x1c
	cp bcnt0,r16
	brcc RESET0						; mehr als 27 klein-Bits angekommen -> Fehler!

	sbrs lastB,0					; jetziger Zustand ist high?
	rjmp ENDE0						; nein -> dann ist es auch nicht fertig!

	lds r16,(0x0063)				; das letzte Byte
	ori r16,0x40					; die übrigen Bits (also die Bits, die eben nicht empfangen wurden)
	sts (0x0063),r16				; des zuerst "empfangenen" Bytes werden alternierend auf 1 gesetzt 

	ldi r26,0x60
	ldi r27,0x00					; Startadresse in den Speicher,
	mov r16,bcnt0					; Bitanzahl in r16
	rcall VERSENDEN					; und ab durch die serielle Schnittstelle

RESET0:
	ldi r16,0x05					; Startbit + '01'=0 (also 0. Empfänger)
	sts (0x0060),r16
	ldi r16,0x00
	sts (0x0061),r16
	sts (0x0062),r16
	sts (0x0063),r16				; empfangene Bits initialisieren
	clr bcnt0						; Bit-Zähler auf 0 setzen

ENDE0:
PIN0WACKELTNICHT:

	sbrs aender,1
	rjmp MAINLOOP
	movw r16,t1moml					; Zählerstand rücksichern

	sub r16,lt1p1l
	sbc r17,lt1p1h					; r17:r16 = TimeDiff

	movw lt1p1l,t1moml				; aktuellen Zählerstand als alten setzen

	subi r16,0xb1
	sbci r17,0x01					; - 865/2 = 0x01b1 = halbes Bit

	brcs RESET1						; zu kurzes Bit -> Fehler!

	subi r16,0x61
	sbci r17,0x03					; - 865   = 0x0361 = kurzes Bit
	brcc KEINKURZESBIT1
	
	clr r16							; wird einfach gespeichert!
	inc bcnt1
	rjmp WEITER1
KEINKURZESBIT1:
	subi r16,0x61
	sbci r17,0x03					; - 865   = 0x0361 = (noch ein) kurzes Bit (= langes Bit)
	brcc RESET1						; zu langes Bit -> Fehler

	inc bcnt1
	inc bcnt1
	ldi r16,0x01					; wird doppelt gespeichert!

WEITER1:
	clc
	sbrs lastB,1					; alten Pinzustand
	sec								; nach C
	lds r17,(0x0064)				; das erste der insgesamt vier Bytes von empfangenen Bits
	rol	r17
	sts (0x0064),r17
	lds r17,(0x0065)
	rol r17
	sts (0x0065),r17
	lds r17,(0x0066)
	rol r17
	sts (0x0066),r17
	lds r17,(0x0067)
	rol r17
	sts (0x0067),r17
	brcs RESET1						; es kamen mehr als 32 Bits an -> Fehler!

	subi r16,0x01
	brcc WEITER1

	ldi r16,0x1a
	cp bcnt1,r16

	brcs ENDE1						; noch keine 26 klein-Bits angekommen -> Ende

	ldi r16,0x1c
	cp bcnt1,r16
	brcc RESET1						; mehr als 27 klein-Bits angekommen -> Fehler!

	sbrs lastB,1					; jetziger Zustand ist high?
	rjmp ENDE1						; nein -> dann ist es auch nicht fertig!

	lds r16,(0x0067)				; das letzte Byte
	ori r16,0x40					; die übrigen Bits (also die Bits, die eben nicht empfangen wurden)
	sts (0x0067),r16				; des zuerst "empfangenen" Bytes werden alternierend auf 1 gesetzt 

	ldi r26,0x64
	ldi r27,0x00					; Startadresse in den Speicher,
	mov r16,bcnt1					; Bitanzahl in r16
	rcall VERSENDEN					; und ab durch die serielle Schnittstelle

RESET1:
	ldi r16,0x03					; Startbit + '10'=0 (also 1. Empfänger)
	sts (0x0064),r16
	ldi r16,0x00
	sts (0x0065),r16
	sts (0x0066),r16
	sts (0x0067),r16				; empfangene Bits initialisieren
	clr bcnt1						; Bit-Zähler auf 0 setzen

ENDE1:
PIN1WACKELTNICHT:

	rjmp MAINLOOP

TIMER0COMPA:
	push r16
	in r16,SREG
	push r16

	sbrc sbuff0,0
	sbi PORTA,1
	sbrs sbuff0,0
	cbi PORTA,1

;	clc								; so werden die Daten zyklisch gesendet
;	sbrc r0,0
	sec

	ror sbuff4
	ror sbuff3
	ror sbuff2
	ror sbuff1
	ror sbuff0

	pop r16
	out SREG,r16
	pop r16

	reti							; TIMER0COMPA

WARTEAUFSENDBUFFER:					; wartet, bis der Sende-Puffer leer ist
	ldi r16,0xff
	cp sbuff4,r16
	brne WARTEAUFSENDBUFFER
	cp sbuff3,r16
	brne WARTEAUFSENDBUFFER
	cp sbuff2,r16
	brne WARTEAUFSENDBUFFER
	cp sbuff1,r16
	brne WARTEAUFSENDBUFFER
	cp sbuff0,r16
	brne WARTEAUFSENDBUFFER
	ret								; WARTEAUFSENDBUFFER

VERSENDEN:							; versendet r16/2+1 Bit Manchester-kodierte Daten
									; aus DRAM, Adresse r27:r26 (=X), base64-kodiert

	movw r18,r26					; Speicheradresse merken
	sbrc r16,0
	rjmp VERSENDENNICHTSCHIEBEN
	sec
	ld r17,X
	rol r17
	st X+,r17
	ld r17,X
	rol r17
	st X+,r17
	ld r17,X
	rol r17
	st X+,r17
	ld r17,X
	rol r17
	st X+,r17
	movw r26,r18
VERSENDENNICHTSCHIEBEN:
	lsr r16
	ldi r17,0x0d
	cpse r16,r17					; nicht 26 halb-Bits?
	ret								; -> Fehler!
	
;		ld r18,X+
;		ld r18,X+
;		ld r18,X+
;		ld r17,X+
;		clr r16
;		rjmp AUSLESESCHLEIFENENDE

	ldi r20,0x03
ALTERNIERENDTESTSCHLEIFE:	
	ld r16,X+
	mov r17,r16
	lsr r16
	eor r16,r17
	andi r16,0x55
	ldi r17,0x55
	cpse r16,r17					; Bits alternierend?
	ret								; nein -> Ende!
	
	subi r20,0x01
	brcs ALTERNIERENDTESTSCHLEIFEENDE
	rjmp ALTERNIERENDTESTSCHLEIFE
ALTERNIERENDTESTSCHLEIFEENDE:

	movw r26,r18
	clr r18
	clr r17
	clr r16

	ldi r19,0x10					; 16 Bits zu lesen (13 reale Bits + 3 Geistbits)
AUSZENSCHLEIFE:
	ld r20,X+
	ldi r21,0x04					; 4 Bits je Byte
INNENSCHLEIFE:
	ror r20
	ror r20
	rol r18
	rol r17
	rol r16
	subi r19,0x01
	breq AUSLESESCHLEIFENENDE
	subi r21,0x01
	brne INNENSCHLEIFE
	rjmp AUSZENSCHLEIFE
AUSLESESCHLEIFENENDE:

	; die zu sendenden 18 Bit Informationen liegen in r16(2):r17(8):r18(8)

	rol r18
	rol r17
	rol r16
	rol r18
	rol r17
	rol r16

	lsr r18
	lsr r18

	rol r17
	rol r16
	rol r17
	rol r16

	lsr r17
	lsr r17

	rcall TOBASE64
	push r16
	mov r16,r17
	rcall TOBASE64
	push r16
	mov r16,r18
	rcall TOBASE64
	push r16
	; die zu sendenden Zeichen liegen auf dem Stack (3., 2., 1.)
	rcall WARTEAUFSENDBUFFER
	
	cli

	clc

	; aus logistischen Gründen füllen wir den Puffer von hinten nach vorne

	ldi r16,0x0d					; 0x0d (CR)
	mov sbuff4,r16
	
	pop r17
	ldi r16,0x40
	sec
	ror r17
	ror r16
	ror r17
	ror r16
	mov sbuff3,r17

	pop r17
	swap r17
	mov r18,r17
	andi r18,0x0f
	or r16,r18
	mov sbuff2,r16

	andi r17,0xf0
	ori r17,0x04
	pop r18
	clr r16
	clc
	rol r18
	rol r16
	sec
	rol r18
	rol r16
	or r16,r17
	mov sbuff1,r16

	mov sbuff0,r18

	sei
	
VERSENDENENDE:
	ret								; VERSENDEN

TOBASE64:							; konvertiert Bit 0-5 von r16 in base64
					; 0-25:  A-Z: +0x41 (=-0xbf)
					; 26-51: a-z: +0x47 (=-0xb9)
					; 52-61: 0-9: -0x04
					; 62:    +:   -0x13
					; 63:    /:   -0x10
	andi r16,0x3f					; zur Sicherheit
	cpi r16,26
	brcc NICHT0BIS25
	subi r16,0xbf
	ret								; TOBASE64
NICHT0BIS25:
	cpi r16,52
	brcc NICHT26BIS51
	subi r16,0xb9
	ret								; TOBASE64
NICHT26BIS51:
	cpi r16,62
	brcc NICHT52BIS61
	subi r16,0x04
	ret								; TOBASE64
NICHT52BIS61:
	cpi r16,63
	brcc NICHT62
	subi r16,0x13
	ret								; TOBASE64
NICHT62:
	subi r16,0x10
	ret								; TOBASE64