File: crrcsim_at90s1200.asm

package info (click to toggle)
crrcsim 0.9.13-3.2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, forky, sid, trixie
  • size: 22,176 kB
  • sloc: cpp: 43,186; xml: 5,022; sh: 3,832; makefile: 501; asm: 228; ansic: 150
file content (275 lines) | stat: -rw-r--r-- 7,767 bytes parent folder | download | duplicates (4)
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
;; Written by Jan Kansky, 5/15/2001.
;;
;; Copyright (C) 2001  Jan Edward Kansky  - kansky@jeklink.net
;;
;; This program is free software; you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation; either version 2 of the
;; License, or (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful, but
;; WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
;; General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program; if not, write to the Free Software
;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

	;; .device	AT90S1200
	.include "1200def.inc"

	;; ***** Global Register Variables

	.def ch1_lsb=r0
	.def ch1_msb=r1
	.def ch2_lsb=r2
	.def ch2_msb=r3
	.def ch3_lsb=r4
	.def ch3_msb=r5
	.def ch4_lsb=r6
	.def ch4_msb=r7
	.def ch5_lsb=r8
	.def ch5_msb=r9
	.def ch6_lsb=r10
	.def ch6_msb=r11
	.def ch7_lsb=r12
	.def ch7_msb=r13
	.def ch8_lsb=r14
	.def ch8_msb=r15
	.def ch9_lsb=r16
	.def ch9_msb=r17
	.def ch10_lsb=r18
	.def ch10_msb=r19
	.def temp=r20
	.def save_state=r21
	.def current_ppm=r22	; Current input channel for PPM decoding
	.def current_out=r23	; Current output nibblet for LPT interface*2
	.def timer_val=r24	; Timer value at PPM irq
	.def overflows=r25	; Number of timer overflows since last PPM irq
	.def num_channels=r26
	.def temp2=r27
	.def y_low_byte=r28
	.def temp5=r29
	.def temp3=r30
	.def temp4=r31

	;; ***** Code
.cseg
.org 0
	rjmp	RESET		; Reset interrupt handler
	rjmp	PPM_INTERRUPT
	rjmp	TIMER_OVERFLOW
	rjmp	RESET
RESET:	ldi temp,$1f		; PB4 is the PtrClk output, lsn out
	out DDRB,temp
	ldi temp,$F0		; PtrClk high, enable pullups on top 3 bits
	out PORTB,temp		;  No wait signal, msn pullups on
	ldi temp,$00
	out DDRD,temp		;  Port D are all not used, so set to inputs
	ldi temp,$FB
	out PORTD,temp		; activate all pullups on PORTD, except irq
	ldi temp,$00
	mov ch1_lsb,temp	; Set all channel values to zero initially
	mov ch1_msb,temp
	mov ch2_lsb,temp
	mov ch2_msb,temp
	mov ch3_lsb,temp
	mov ch3_msb,temp
	mov ch4_lsb,temp
	mov ch4_msb,temp
	mov ch5_lsb,temp
	mov ch5_msb,temp
	mov ch6_lsb,temp
	mov ch6_msb,temp
	mov ch7_lsb,temp
	mov ch7_msb,temp
	mov ch8_lsb,temp
	mov ch8_msb,temp
	mov ch9_lsb,temp
	mov ch9_msb,temp
	mov ch10_lsb,temp
	mov ch10_msb,temp
	mov num_channels,temp	;  Number of detected channels initialized to 0
	mov current_ppm,temp	;  Current channel is 0, indicating not synched
	ldi current_out,0	;  Nibble 0 is to be output on LPT
	mov overflows,temp	;  No 8 bit timer overflows have occured.
	clr y_low_byte		;  Starting outputting channel 1 lsn
	mov num_channels,temp   ;  No channels have been detected.
	ldi temp,$02		;  Set falling edge interrupts.
	out MCUCR,temp
	ldi temp,$40
	out GIMSK,temp		;  Enable external interrupt
	ldi temp,$02
	out TIFR,temp
	out TIMSK,temp		;  Enable timer overflow irqs
	sei			;  Enable interrupts
	ldi temp,1
	out TCCR0,temp		;  Timer running with no prescaling
	ldi temp,$00
	out TCNT0,temp
	ldi temp2,$00
	
START:	mov temp3,y_low_byte	;  Copy current byte address to Z register
	ld temp,Z		;  Load data to prepare for output
	ldi temp2,$F0		;  Keep pullups on, and PtrClk high for now
	sbrc current_out,0	;  See if we are on an odd nibble
	swap temp		;  if so then swap nibbles
	andi temp,$0F		;  Mask of least significant nibble
	or temp2,temp		;  Or that nibble into the output byte
	ldi temp,$F0		;  Set PtrClk, maintain pullups
	cpi y_low_byte,0	;  See if we should output a sync pulse
	brne sync_it_up		;  Current output channel is zero
	cpi current_out,0	;  Current nibble output is zero
	brne sync_it_up
	ldi temp,$F1		;  Set PtrClk, maintain pullups, set sync
sync_it_up:	
	out PORTB,temp
POLL:	sbic PINB,5		;  Wait for host to ask for data
	rjmp POLL
	out PORTB,temp2		;  Output data to host
	andi temp2,$EF		;  Set Ptr Clock low, indicating data ready
	out PORTB,temp2		;  Output data to host
	inc current_out		;  Add one to prepare for next nibble output
	cpi current_out,$02	;  If we just finished outputting second nibble
	brne dont_update_y
	inc y_low_byte		;  increment the byte address
dont_update_y:		
	cpi current_out,$03	;  If we finished the third nibble, start over
	brlo channel_not_done
	ldi current_out,0	;  Back to starting nibble
	inc y_low_byte		;  Switch to next channel
channel_not_done:
REPLY:	sbis PINB,5		;  Wait for host to finish reading data
	rjmp REPLY		
	cpi y_low_byte,$14	;  If done with 20 bytes, (9 channels+1 sync)*2
	brne cycle_not_done
	inc y_low_byte		;  Increment address so irqs still registers
no_new_data_yet:	
	cpi temp4,$FF		;  Wait for new frame of data to complete
	brne no_new_data_yet
	ldi temp4,$00
	ldi temp,$F1		;  Tell host we are ready to transfer new frame
	out PORTB,temp
dont_go_back_to_zero_yet:
	sbic PINB,5		;  Wait for host to ask for new frame
	rjmp dont_go_back_to_zero_yet
	clr y_low_byte		;  Reset address to zero
cycle_not_done:	
	rjmp START

TIMER_OVERFLOW:
	in save_state,SREG
	inc overflows
	out SREG,save_state
	reti
	
PPM_INTERRUPT:
	in save_state,SREG
	ldi temp4,0
	out TCCR0,temp4		;  Stop timer
	mov temp5,temp3		;  Backup Z register
	in timer_val,TCNT0	;  Read timer value
	in temp4,TIFR		;  Read in Timer interrupt flag register
	ldi temp3,$00		;  Reset counter to zero, prepare for next irq
	out TCNT0,temp3
	ldi temp3,1
	out TCCR0,temp3		;  Timer running with no prescaling	
	sbrs temp4,1
	rjmp no_overflow	;  If not set, continue
	inc overflows		;  Increment overflow counter
	ldi temp3,$02
	out TIFR,temp3		;  Clear the overflow
no_overflow:
	cpi overflows,$0E	; Check if this is a sync pulse
	brlo check_sync		; If not, put data into appropriate channel
	ldi current_ppm,1	; if it is reset channel counter to first chanl
	mov temp4,y_low_byte	; Check to make sure we aren't currently
	lsr temp4		;  sending this data to the LPT	
	ldi temp3,$09	  
	cp temp3,temp4
	breq dont_change_now
	mov temp3,timer_val
	lsr temp3
	lsr temp3
	lsr temp3
	mov temp4,overflows
	sbrc temp4,0
	sbr temp3,$20
	sbrc temp4,1
	sbr temp3,$40
	sbrc temp4,2
	sbr temp3,$80
	lsr temp4
	lsr temp4
	lsr temp4
	mov ch10_lsb,temp3	; Store the sync pulse width in ch10
	mov ch10_msb,temp4	; this will allow for total cycle time comp.
	mov temp3,num_channels  ; Clear unused channels
	ldi num_channels,$00
	lsl temp3
continue_clearing:	
	cpi temp3,$12		; See if we've cleared up to and including 9
	breq done_clearing
	st Z,num_channels	;  Clear low byte
	inc temp3
	st Z,num_channels	;  Clear high byte
	inc temp3
	rjmp continue_clearing
done_clearing:	
	ldi temp4,$FF
dont_change_now:		
	rjmp exit_ppm		; and exit to await next irq
check_sync:	
	cpi current_ppm,0	; If not a sync pulse, check to see if we
	brne save_data		; have achieved sync.  If not, exit, else
	rjmp exit_ppm		; see which channel the irq belongs to.
save_data:
	cp current_ppm,num_channels;  Determine how many channels are 
	brlo not_new_max	; being output by the radio transmitter
	mov num_channels,current_ppm
not_new_max:
	mov temp4,y_low_byte	; Check to make sure we aren't currently
	lsr temp4		;  sending this data to the LPT
	mov temp3,current_ppm	;  Prepare Z register for Immediate with offset
	dec temp3
	cp temp3,temp4
	breq dont_save
	lsl temp3
	ldi temp4,0
	st Z,timer_val
	inc temp3
	st Z,overflows
dont_save:	
	ldi temp3,0
	ldi temp4,9
	cp current_ppm,temp4
	brlo done_ppm
	dec current_ppm	  ; Decrement current_ppm so ch 10 or higher go into 9
done_ppm:	
	inc current_ppm		; Increment for the next channel
exit_ppm:	
	ldi overflows,0
	mov temp3,temp5		;  Restore Z register
	out SREG,save_state
	reti