Keelan vor 2 Jahren
Commit
f2b8ed2b76
5 geänderte Dateien mit 1554 neuen und 0 gelöschten Zeilen
  1. 5
    0
      Makefile
  2. 5
    0
      README.md
  3. 297
    0
      adb.asm
  4. 178
    0
      adb.inc
  5. 1069
    0
      adbio.asm

+ 5
- 0
Makefile Datei anzeigen

@@ -0,0 +1,5 @@
1
+ASM=gpasm
2
+
3
+adbio.hex: adbio.asm adb.inc adb.asm
4
+	$(ASM) adbio.asm
5
+	

+ 5
- 0
README.md Datei anzeigen

@@ -0,0 +1,5 @@
1
+# ADBIO PIC Firmware
2
+
3
+Target: PIC16F88
4
+
5
+Currently 100% untested. This is based on Microchip's AN591 code, which I found to be terribly structured, and riddled with errors. I probably should have just abandoned it and started from scratch. But I didn't.

+ 297
- 0
adb.asm Datei anzeigen

@@ -0,0 +1,297 @@
1
+;*** PrScale ROUTINE CALLED AT END OF AttnSig AND Srq SIGNALS
2
+
3
+
4
+PreScale8
5
+		banksel OPTION_REG
6
+		movlw	b'00000010'				; BINARY - set to prescale RTCC
7
+		movwf	OPTION_REG				; Clear 4th bit from right to select RTCC
8
+		banksel TMR0
9
+		clrf	TMR0					; last 3 bits set prescale value as 1:4
10
+		retlw	00h						; this gives a good ratio to monitor the
11
+										; timing for Reset and Attention signals and
12
+										; the 2nd Application Task
13
+
14
+;*** NoPrScl ROUTINE CALLED AT BEGINNING OF SyncSig AND END OF Srq SIGNALS
15
+PreScale2
16
+		banksel OPTION_REG
17
+		movlw	b'00000000'				; BINARY - set to prescale RTCC
18
+		movwf	OPTION_REG				; Clear 4th bit from right to select RTCC
19
+		banksel TMR0
20
+		clrf	TMR0					; last 3 bits set prescale value as 1:4
21
+		retlw	00h						; this gives a good ratio to monitor the
22
+										; timing for Reset and Attention signals and
23
+										; the 2nd Application Task
24
+
25
+
26
+;***************************************************************************
27
+
28
+;*** GET INCOMING BIT & INTERPRET WHETHER IT'S A '1' OR A '0' *** (Get_Bit) ***
29
+;*** Get_Bit CALLED BY COMMAND AND LISTEN ROUTINES
30
+; Get the bit, find out whether it's less than or greater than 50 usecs, 
31
+; if < than 50 usecs, it's a '1' bit
32
+; if > than 50 usecs, it's a '0' bit
33
+; if it's a '1' bit, set LSB in the reg. pointed to by the FSR (Command Byte)
34
+; if it's a '0' bit, do nothing to the LSB
35
+; then look for the end of the Bit Cell (104 usecs max.)
36
+; if the maximum Bit time of (72 usecs) or maximum Bit Cell time is exceeded,
37
+; abort to the Attn Signal
38
+
39
+Get_Bit banksel TMR0
40
+		movf	TMR0,w					; Check the time, then check if the line went high:
41
+		subwf	TimeVar,w				; See if more than BIT_TST usecs have passed
42
+		btfss	STATUS,C				; if not, check whether the line went high
43
+		goto	AttnSig					; if so, abort to the Attn Signal
44
+		btfss	PORTA,ADBPin			; Check whether the line went high
45
+		goto	Get_Bit					; if line is still low, loop again
46
+		movlw	BIT_TST					; if line went high, see if it's a '1' or a '0'
47
+		movwf	TimeVar					; as the bit has not yet been determined yet,
48
+		bcf		INDF,0					; ensure the LSB in the indirect address is '0'
49
+		movf	TMR0,W					; Get the time
50
+		subwf	TimeVar,W				; if time < 50 usecs, it's a '1' bit
51
+		btfsc	STATUS,C				; if time > 50 usecs and < 72, it's a '0' bit
52
+		bsf		INDF,0					; if it's a 1, set LSB in the address FSR points to
53
+		movlw	BITCELL					; Check whether the Max. Bit Cell time of 104 usecs
54
+		movwf	TimeVar					; has been exceeded
55
+CellChk movf	TMR0,W					; Check the time, then check the line
56
+		subwf	TimeVar,W				; See if more than Max. Bit Cell usecs have passed
57
+		btfss	STATUS,C				; if not, look for the line to go low again
58
+		goto	AttnSig					; if so, abort to the Attn Signal or Reset
59
+		btfsc	PORTA,ADBPin			; Check the line for the start of another bit
60
+		goto	CellChk					; if the line is still high, loop CelChk1 again
61
+		clrf	TMR0					; if the line went low, clear the RTCC & return
62
+		retlw	00h						; 	for another bit or to interpret the Command
63
+
64
+
65
+
66
+;***************************************************************************
67
+
68
+
69
+
70
+
71
+;*** MASK OUT COMMAND NIBBLE AND REG.# BITS FROM THE COMMAND *** (MaskCmd) ***
72
+; NOTE: This routine should only be called once during any single ADB 
73
+; transaction, from either AddrChk or CmmdChk
74
+
75
+; Command Byte:
76
+; |	7	|		6	|	5	|		4	|	3	|		2	|	1	|		0	|
77
+; |	A3 |		A2 |	A1 |		A0 | Cmd Code	|	Register |
78
+
79
+DecodeCmd 
80
+		assume	bank0
81
+
82
+		movf	CmdByte, w
83
+		andlw	0xF0
84
+		movwf	ReqAddress
85
+		swapf	ReqAddress, f
86
+
87
+		movf	CmdByte, w
88
+		andlw	0x03
89
+		movwf	ReqReg
90
+		addwf	ReqReg, w				; multiply reg by 2 to get 16 bit register offset
91
+		addlw	Reg0a					; add base address of register memory area
92
+		movwf	RAMaddr					; store pointer
93
+
94
+
95
+		call	SetCmdFlags				; use a jump table to translate the 16 
96
+		movwf	ReqCommand				; possible combinations of commands into a
97
+
98
+
99
+		; turn ReqReg into bit field so we can use btfss elsewhere
100
+
101
+		btfsc	ReqReg, 1
102
+		goto	$+5
103
+		movlw	0x01					; 00
104
+		btfsc	ReqReg, 0
105
+		movlw	0x02					; 01
106
+		goto	storVal
107
+		movlw	0x04					; 10
108
+		btfsc	ReqReg, 0
109
+		movlw	0x08					; 11
110
+storVal movwf	ReqReg
111
+
112
+		return
113
+
114
+SetCmdFlags
115
+
116
+		movf	CmdByte, w
117
+		andlw	0x0F
118
+		addlw	SetCmdFlagsJump
119
+
120
+SetCmdFlagsJump
121
+
122
+		retlw	1<<cmdReset				; 0
123
+		retlw	1<<cmdFlush				; 1
124
+		retlw	1<<cmdReserved			; 2
125
+		retlw	1<<cmdReserved			; 3
126
+		retlw	1<<cmdReserved			; 4
127
+		retlw	1<<cmdReserved			; 5
128
+		retlw	1<<cmdReserved			; 6
129
+		retlw	1<<cmdReserved			; 7
130
+		retlw	1<<cmdListen			; 8
131
+		retlw	1<<cmdListen			; 9
132
+		retlw	1<<cmdListen			; A
133
+		retlw	1<<cmdListen			; B
134
+		retlw	1<<cmdTalk				; C
135
+		retlw	1<<cmdTalk				; D
136
+		retlw	1<<cmdTalk				; E
137
+		retlw	1<<cmdTalk				; F
138
+
139
+
140
+
141
+
142
+
143
+
144
+
145
+
146
+;***************************************************************************
147
+
148
+;*** ISSUE A SERVICE REQUEST IF NECESSARY *** (Srq; may call LineLow) ***
149
+;*** CALLED BY AddrChk
150
+; see if the Srq Flag is set, if not, return, otherwise:
151
+; change the prescaler to RTCC since this takes longer than 255 usecs,
152
+; load the SRQTIME of 300 usecs into the TimeVariable,
153
+; call LineLow to:
154
+; 	keep checking the time to see if 300 usecs have passed,
155
+; 	let the line go high again, 
156
+; 	and see if the line is high, and if not, abort, if it is,
157
+; change the prescaler back to WDT, and return 
158
+
159
+SendSrq 
160
+		call	PreScale8				; switch the prscaler to RTCC
161
+		banksel TRISA
162
+		bcf		TRISA, ADBPin			; tri-state PORTA to make the ADB an output
163
+		movlw	SRQ_MAX
164
+		call	LineLow
165
+		call	PreScale2				; change the prescaler back to WDT
166
+		return
167
+
168
+;***************************************************************************
169
+
170
+;*** Tlt - TIME FROM STOP BIT TO START BIT ***	(Tlt) ***
171
+;*** CALLED BY EITHER Talk OR Listen ROUTINES
172
+; Loop checking the time, then checking the line to see if it went low
173
+; if at any time the line goes low,
174
+; 	see if this is a Talk Command, 
175
+; 		if it is a Talk Commmand, go to the Collision routine
176
+; if the line goes low before the minimum Tlt time, abort to Attn Signal
177
+; if the line is high longer than TLT_Min usecs, 
178
+; 	see if this is a Talk Command, and if it is, wait for the mid-point,
179
+; 		and return to Send the Start Bit, Data Bytes, & the Stop Bit
180
+; 	if it's not a Talk Command, see if it's a Listen Command, and if so,
181
+; 		load Tlt_Max for TimeVariable, and look for the line to go 
182
+; 			low as the beginning of the Start Bit,
183
+; 	if more than Tlt_Max usecs pass, abort to Attn Signal
184
+; if the line goes low and this is a Listen Command,
185
+; 	clear the RTCC & return to get the rest of the Start Bit
186
+
187
+Tlt		movlw	TLT_MIN					; Look for Stop-to-Start-Time, Tlt
188
+		banksel TimeVar
189
+		movwf	TimeVar					; Check the time, then check the line
190
+TltChk1 movf	TMR0,W					; See if more than TLT_MIN usecs have passed
191
+		xorwf	Random,F				; (ensure the Talk R3 address is Random with XOR)
192
+		subwf	TimeVar,W				; by checking whether Carry bit is set
193
+		btfss	STATUS,C				; 	after subtraction
194
+		goto	ChkFlag					; if TLT_MIN usecs passed, see what Command this is
195
+		btfsc	PORTA, ADBPin			; if not, check whether the line went low
196
+		goto	TltChk1					; if the line is still high, keep looping
197
+		btfsc	Flags1,F1Talk			; if line went low, see if this is a Talk Command
198
+		goto	Collisn					; 	if it is, there was a Collision, abort
199
+		movf	TMR0,W					; otherwise, check the time
200
+		subwf	TimeVar,W				; 	 see if TLT_MIN usecs passed,
201
+		btfss	STATUS,C				; 	 if not, abort to Attn Signal, too little
202
+		goto	AttnSig					; 		time passed when the line went low
203
+		clrf	TMR0					; if it's not a Talk Command, clear the RTCC and
204
+		retlw	00h						; 	return for the rest of the Start Bit 
205
+		
206
+ChkFlag banksel Flags1
207
+		btfsc	Flags1,F1Talk			; Check whether to Talk or Listen
208
+		goto	TltTalk					; if Talk, wait for mid-point of Tlt time
209
+		btfss	Flags1,F1Lstn			; if Listen, continue to look for Start Bit
210
+		retlw	00h						; if neither flag is set, abort, something's wrong
211
+		movlw	TLT_MAX					; Load TimeVariable to check for upper limit 
212
+		movwf	TimeVar					; 	of Tlt time
213
+TltChk2 movf	TMR0,W					; See if TLT_MAX usecs have been exceeded
214
+		subwf	TimeVar,W				; by checking whether Carry bit is set
215
+		btfss	STATUS,C				; 	after subtraction
216
+		goto	AttnSig					; if so, abort to Attn Signal
217
+		btfsc	PORTA,ADBPin			; if not, check whether the line went low
218
+		goto	TltChk2					; if line is still high, check the time again
219
+		btfsc	Flags1,F1Talk			; if line went low, see if this is a Talk Command
220
+		goto	Collisn					; 	if so, there was a Collision
221
+		clrf	TMR0					; 	if it's not a Talk Command, return to get
222
+		retlw	00h						; 	the rest of the Start Bit from Host
223
+
224
+TltTalk movlw	TLT_MID					; Load TimeVariable so Talk will send Start Bit at 
225
+		banksel TimeVar
226
+		movwf	TimeVar					; about the mid-point of the Tlt 
227
+TltChk3 movf	TMR0,W					; See if TLT_MID usecs have been exceeded
228
+		subwf	TimeVar,W				; by checking whether Carry bit is set
229
+		btfss	STATUS,C				; 	after subtraction
230
+		retlw	00h						; if time was exceeded, return to send Start Bit
231
+		btfsc	PORTA, ADBPin			; if not, check whether the line went low
232
+		goto	TltChk3					; if line is still high, check the time again
233
+		goto	Collisn					; if the line went low, abort to Collision
234
+
235
+
236
+Collisn	banksel	bank1
237
+		btfsc	ReqReg, 3				; if there was a collision during a Talk Reg. 3
238
+		bsf	 	Flags1, F1Cllsn			; Command, then set the Collision Flag,
239
+		goto	AttnSig					; otherwise, just abort to Attn Signal
240
+
241
+;***************************************************************************
242
+
243
+
244
+SendLow	
245
+		movlw	LOW0BIT					; Send a '0' bit									
246
+		call	LineLow					; hold the line low for 2/3rd of a Bit Cell
247
+		movlw	HI_0BIT
248
+		call	LineHi					; let the line high for the rest of the Bit Cell
249
+		return
250
+
251
+SendHigh
252
+		movlw	LOW1BIT					; Send a '1' bit									
253
+		call	LineLow					; hold the line low for 1/3rd of a Bit Cell
254
+		movlw	HI_1BIT														
255
+		call	LineHi					; let the line high for the rest of the Bit Cell
256
+		return
257
+
258
+
259
+
260
+
261
+
262
+;*** MAKE LINE GO LOW TIME IN TimeVar AS A '1' OR '0' BIT *** (LineLow) ***
263
+;*** CALLED BY Talk OR Srq
264
+
265
+LineLow movwf	TimeVar
266
+Low_Tmp movf	TMR0,W					; Check the clock,
267
+		subwf	TimeVar,W				; loop until TimeVar usecs have passed 
268
+		skpnc
269
+		goto	Low_Tmp
270
+		banksel bank1					; Tri-state PORTA to make ADB line an input again
271
+		bsf		TRISA, ADBPin			; and let the line go high
272
+		banksel bank0
273
+		clrf	TMR0					; and clear RTCC
274
+		goto $+1						; Allow the ADB Port line to stabilize
275
+		goto $+1						; Allow the ADB Port line to stabilize
276
+		btfss	PORTA, ADBPin			; check if the line is still low, if so, a
277
+		goto	Collisn					; Collision occurred
278
+		retlw	00h						; if not, return to load high time for rest of bit
279
+
280
+;*** MAKE LINE GO HIGH FOR REST OF BIT CELL TIME IN TimeVar *** (LineHi) ***
281
+;*** CALLED BY Talk
282
+
283
+LineHi	movwf	TimeVar					; Let the line go high for a pre-designated time
284
+Hi_Tmp	movf	TMR0,W					; Check the clock, 
285
+		subwf	TimeVar,W				; loop until TimeVar usecs have passed
286
+		skpnc
287
+		goto	Hi_Tmp
288
+		btfss	PORTA, ADBPin			; check if the line is still high,
289
+		goto	Collisn					; if not, a Collision occurred, Abort
290
+		btfsc	Flags1,F1Stop			; if this is the end of the Data Stop Bit, don't
291
+		retlw	00h						; let the line go low again, just return
292
+		banksel bank1					; if still high, start sending a bit to the Host
293
+		bcf		TRISA, ADBPin			; tri-state PORTA to make the ADB an output and
294
+		banksel bank0
295
+		clrf	TMR0
296
+		retlw	00h	
297
+

+ 178
- 0
adb.inc Datei anzeigen

@@ -0,0 +1,178 @@
1
+bank0		equ		00h
2
+bank1		equ		80h
3
+bank2		equ		100h
4
+bank3		equ		180h
5
+
6
+; *** BIT ASSIGNMENTS FOR I/O LINES & TRI-STATING
7
+
8
+ADBIOPrtATRIS	equ		TRISB
9
+ADBIOPrtBTRIS	equ		TRISA
10
+
11
+ADBPin		equ		RA4	 	; Port A Pin used for ADB
12
+ADBAltPin	equ		RB0	 	; Port B Pin used for ADB (currently unused)
13
+ADBIOIDH	equ		RB1		; Unit ID high bit (SW1)
14
+ADBIOIDL	equ		RB2		; Unit ID high bit (SW2)
15
+
16
+ADBIOPortB	equ		PORTA
17
+ADBIOPinB1	equ		RA0
18
+ADBIOPinB2	equ		RA1
19
+ADBIOPinB3	equ		RA2
20
+ADBIOPinB4	equ		RA3
21
+
22
+ADBIOPortA	equ		PORTB
23
+ADBIOPinA1	equ		RB7
24
+ADBIOPinA2	equ		RB6
25
+ADBIOPinA3	equ		RB5
26
+ADBIOPinA4	equ		RB4
27
+
28
+;*** MISC. CONSTANTS
29
+
30
+DefaultAddr	equ		07h	 			; default device address to start with (Assigned by Apple)
31
+DefaultID	equ		7Ah				; default ID (Assigned by Apple)
32
+									;   Data storage registers
33
+
34
+
35
+;*** DATA HANDLER ID MASKS: MASK DATA REGISTER 3b FOR:
36
+
37
+SELFTST equ	0FFh	 ; Self-Test mode
38
+LISTEN1 equ	  0h	 ; unconditional address change
39
+LISTEN2 equ	0FEh	 ; address change if no collision detected
40
+DEV_ACT equ	0FDh	 ; address change if device activator is depressed
41
+
42
+
43
+;*** BITS USED IN THE UPPER NIBBLE OF REGISTER 3a FOR SPECIAL ADB STATUS BITS
44
+
45
+Resrvd3 equ	 04h	  ; reserved (Always 0)
46
+Srq_Bit equ	 05h	  ; determines if Host will accept Service Requests
47
+ExpEvnt equ	 06h	  ; indicates an Exceptional Event should take place
48
+Always0 equ	 07h	  ; always set to 0
49
+
50
+
51
+;*** ADB FLAG BITS IN THE "FLAGS1" REGISTER (F1 indicates 1st Flags register)
52
+
53
+F1Attn  equ	 00h	 ; set to know if 2nd Task taking place during Attn
54
+F1Talk  equ  02h     ; indicates to Tlt routine this is a Talk Command
55
+F1Stop  equ	 03h	 ; set to indicate the Data Stop Bit is being sent
56
+F1Lstn  equ	 04h	 ; indicates to Tlt routine this is a Listen Command
57
+
58
+F1Rcvd1 equ	 06h	 ; 1st byte of Data Register has been received
59
+F1Cllsn equ	 07h	 ; set to indicate that a collision occurred
60
+
61
+
62
+;*** FLAG BITS IN THE "FLAGS2" REGISTER (F2 indicates 2nd Flags register)
63
+
64
+F2Srq		equ	 	00h				; indicate that Srq should be issued
65
+F2STest		equ		03h				; set to indicate a device Self Test is to be performed
66
+F2SFail		equ		04h				; set to indicate that the Device Self-Test Failed
67
+F2DRcvd		equ		05h				; set when data is received for 2nd Application Task
68
+
69
+
70
+; Timing Definitions for 8 Mhz clock
71
+; ------------------------------------------------------------------------------
72
+
73
+PrSclr1		equ		d'4'			; TMR0 period (microseconds) when prescaler is set to 8
74
+PrSclr2 	equ		d'1'			; TMR0 period (microseconds) when prescaler is set to 2
75
+
76
+ATT_MIN 	equ		d'776'/PrSclr1	; Attn lower limit: 800 - 3% tolerance = 776 usecs
77
+ATT_MAX 	equ		d'824'/PrSclr1	; Attn upper limit: 800 + 3% tolerance = 824 usecs
78
+TSK2MIN 	equ		d'500'/PrSclr1	; time given to 2nd Task during Attn Signal
79
+TSK2MAX 	equ		d'900'/PrSclr1	; time given to 2nd Task after Data Sent/Received
80
+ADBSYNC 	equ		d'72'/PrSclr2	; Sync with extra tolerance after Attn is detected
81
+BIT_TST 	equ		d'50'/PrSclr2	; if time is < 50 = 1 bit, & > 50 = 0 bit
82
+MAX_BIT 	equ		d'72'/PrSclr2	; Maximum time line can be low for a bit   
83
+BITCELL 	equ		d'104'/PrSclr2	; Maximum time for a bit cell = 104 usecs
84
+TLT_MIN 	equ		d'140'/PrSclr2	; Stop to Start minimum time = 140 usecs
85
+TLT_MAX 	equ		d'250'/PrSclr2	; Stop to Start maximum time = 260 usecs
86
+TLT_MID 	equ		d'180'/PrSclr2	; Stop to Start median time  = 208 usecs
87
+SRQ_MAX 	equ		d'296'/PrSclr1	; amount of time to hold for a Service ReQuest 
88
+
89
+; NOTE: for RTCC timing of sending bits, some extra time is allowed for 
90
+; instruction cycles between the end of the bit and the start of the next bit
91
+
92
+LOW1BIT 	equ		d'22'/PrSclr2	; low time for a 1 bit
93
+HI_1BIT 	equ		d'50'/PrSclr2	; hi time  for a 1 bit
94
+LOW0BIT 	equ		d'56'/PrSclr2	; low time for a 0 bit
95
+HI_0BIT 	equ		d'20'/PrSclr2	; hi time  for a 0 bit
96
+
97
+ 
98
+; bits of ReqCommand
99
+cmdReset	equ		0
100
+cmdFlush	equ		1
101
+cmdListen	equ		2
102
+cmdTalk		equ		3
103
+cmdReserved	equ		4
104
+
105
+reqReg0		equ		0
106
+reqReg1		equ		1
107
+reqReg2		equ		2
108
+reqReg3		equ		3
109
+
110
+cblock 20h			; bank0
111
+	
112
+	DeviceAddr
113
+	
114
+	Reg0a
115
+	Reg0b
116
+	Reg1a
117
+	Reg1b
118
+	Reg2a
119
+	Reg2b
120
+	Reg3a
121
+	Reg3b
122
+	
123
+	ShiftReg
124
+	
125
+	TmpReg1			; temporary registers where Data is sent from & 
126
+	TmpReg2			;  received; NOTE: THESE 2 MUST BE IN THIS ORDER
127
+	
128
+	PortTalkBytes:5
129
+	
130
+	RegNum 			; holds current ADB Data Reg.# - NOT a RAM address
131
+	RAMaddr			; holds RAM address of ADB Data Reg.#
132
+	Flags1 			; two Flags registers used by ADB & 2nd
133
+	Flags2 			;   Application Task
134
+	CmdByte			; holds the Command Byte
135
+	BitCounter			; counts down when sending or receiving bits
136
+	Random 			; stores Random Address sent in Talk routine
137
+	TimeVar			; used with RTCC for all ADB timing
138
+	Tsk2Var			; used with RTCC for timing during 2nd Task
139
+	
140
+	ByteCounter
141
+	
142
+	CommandNibble
143
+	CommandCode
144
+	
145
+	
146
+	ReqAddress
147
+	ReqCommand
148
+	ReqReg
149
+	
150
+	
151
+	TmpCtr1			; being used for debounce in example code
152
+	d1				; used in ADC delay loop
153
+	ADCPort			; used in ADC code
154
+	
155
+	
156
+	PortACfg		; 7:6 = 00, 5:4 = AD Config (always 11 for port A), 3:0 = Port Directions (1 = in)
157
+	PortBCfg 		; 7:6 = 00, 5:4 = AD Config (always 11 for port A), 3:0 = Port Directions (1 = in)
158
+	PortAShadow
159
+	PortBShadow
160
+	UnitID			; 7:6 = Unit ID
161
+	
162
+	A1Timer
163
+	A2Timer
164
+	A3Timer
165
+	A4Timer
166
+	
167
+endc
168
+
169
+
170
+ADBIOPortAShadow	equ	PortBShadow
171
+ADBIOPortBShadow	equ	PortAShadow
172
+
173
+
174
+cblock 70h			; globals
175
+	SaveStatus
176
+	SaveW
177
+endc
178
+

+ 1069
- 0
adbio.asm
Datei-Diff unterdrückt, da er zu groß ist
Datei anzeigen