-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathN64_HAL.sbp
289 lines (234 loc) · 7.59 KB
/
N64_HAL.sbp
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
'--------------------------------- N64 AREA ----------------------------------------------
Sub NUS_InitPorts()
MCP_WriteRegister(MCP23017_GPPUA, &HFF) 'GPIO-A pullup Enable
MCP_WriteRegister(MCP23017_GPPUB, &HFF) 'GPIO-B pullup Enable
FTDI_GPIOA = NUS_WE or NUS_RE 'コントロールpin
NUS_SetCtrlPin(FTDI_GPIOA)
MCP_WriteRegister(MCP23017_IODIRB, SDAT_DDR_IN)
N64PowerOFF()
End Sub
'FT232H-GPIOA
'[SCL][SDO][SDI][CS][NUS_WR][NUS_RD][ALE_L][ALE_H]
'0x80コマンドを使用するときは下位4ビットのSPI系に迷惑をかけないようにする。
Dim FTDI_GPIOA As Byte
Const FTDI_GPIOA_DDR = &HFB
Const NUS_WE = &H10
Const NUS_RE = &H20
Const ALE_L = &H40
Const ALE_H = &H80
'MCP23S17-GPIOB
Const EEP_CLK = &H01
Const EEP_DAT = &H02 'SDAT
Const RESET = &H04
Const NUS_POWER = &H08
Const SDAT_DDR_IN = &H02 '1 = input
Const SDAT_DDR_OUT = &H00
Sub N64PowerON()
MCP_WriteRegister(MCP23017_GPIOB, EEP_CLK or SDAT_DDR_IN)
FTDI_SendCommand()
MCP_WriteRegister(MCP23017_GPIOB, RESET or EEP_CLK)
FTDI_SendCommand()
Sleep(5)
End Sub
Sub N64PowerOFF()
MCP_WriteRegister(MCP23017_GPIOB, NUS_POWER or EEP_CLK)
FTDI_SendCommand()
Sleep(3)
End Sub
Sub NUS_Reset()
MCP_WriteRegister(MCP23017_GPIOB, EEP_CLK)
FTDI_SendCommand()
MCP_WriteRegister(MCP23017_GPIOB, RESET or EEP_CLK)
FTDI_SendCommand()
End Sub
/*
Sub NUS_Clock()
MCP_WriteRegister(MCP23017_GPIOB, 0)
MCP_WriteRegister(MCP23017_GPIOB, EEP_CLK)
End Sub*/
'WE RE ALE_H ALE_Lの制御
Sub NUS_SetCtrlPin(newFT_GPIOA As Byte)
if FTDI_GPIOA And NUS_WE = 0 then debug
'Set N64 control pin
FTDI_GPIOA = (FTDI_GPIOA And &H0F) or (newFT_GPIOA And &HF0)
outbuf[c] = &H80 : c++
outbuf[c] = FTDI_GPIOA : c++
outbuf[c] = FTDI_GPIOA_DDR : c++ '(Out:1 , input:0)
End Sub
Sub NUS_readRequest(nLoop As DWord)
Dim i As Long
For i = 1 To nLoop
NUS_SetCtrlPin(NUS_WE) 'RE -> Low
if slowMode = TRUE then FT_WAIT(15)
MCP_ReadRegister(MCP23017_GPIOA) 'Hibyte Request
outbuf[c] = &H83 : c++ 'LoByte Request
NUS_SetCtrlPin(NUS_WE or NUS_RE) 'RE -> Hi
Next i
End Sub
Enum NUS_BUS_DIRECTION
NUS_BUS_DIR_INPUT = &HFF
NUS_BUS_DIR_OUTPUT = &H00
End Enum
Sub NUS_SetBusDir(dir As NUS_BUS_DIRECTION)
'ACBusの方向設定(1でOutput)
if dir = NUS_BUS_DIR_INPUT then
outbuf[c] = &H82 : c++
outbuf[c] = 00 : c++
outbuf[c] = NOT(dir) And &HFF : c++
endif
'MCP-GPIOAの方向設定(1でInput)
MCP_WriteRegister(MCP23017_IODIRA, dir As Byte )
End Sub
Sub NUS_SetAddress(adr As DWord)
Dim adrHi As Word, adrLo As Word
adrHi = adr>>16
adrLo = adr And &H0000FFFF
NUS_SetBusDir(NUS_BUS_DIR_OUTPUT)
'WE RE ALE_HL -> High[
if slowMode = TRUE then
NUS_SetCtrlPin(&H30) 'ALE_Lは遅らせないと一部カートリッジでアドレスセットに失敗する
FT_WAIT(9)
NUS_SetCtrlPin(&Hb0) 'ALE_Lは遅らせないと一部カートリッジでアドレスセットに失敗する
' FT_WAIT(5)
endif
NUS_SetCtrlPin(&Hf0)
' if slowMode = TRUE then FT_WAIT(20)
'Set N64HiByte
MCP_WriteRegister(MCP23017_GPIOA, adrHi>>8)
outbuf[c] = &H82 : c++
outbuf[c] = adrHi And &H00FF : c++
outbuf[c] = &HFF : c++ 'ALL OUTPUT
'if slowMode = TRUE then FT_WAIT(20)
'ALE_H -> Low
NUS_SetCtrlPin(NUS_WE or NUS_RE or ALE_L)
'Set N64 Low Byte
MCP_WriteRegister(MCP23017_GPIOA, adrLo>>8)
outbuf[c] = &H82 : c++
outbuf[c] = adrLo And &H00FF : c++
outbuf[c] = &HFF : c++ 'ALL OUTPUT
' if slowMode = TRUE then FT_WAIT(15)
'ALE_L -> Low
NUS_SetCtrlPin(NUS_WE or NUS_RE)
' if slowMode = TRUE then FT_WAIT(1500)
NUS_SetBusDir(NUS_BUS_DIR_INPUT)
' printf(ex"[SetAddress] %08x\n", adr)
End Sub
Sub NUS_writeData(outData As Word)
NUS_SetBusDir(NUS_BUS_DIR_OUTPUT)
MCP_WriteRegister(MCP23017_GPIOA, outData>>8)
outbuf[c] = &H82 : c++
outbuf[c] = outData And &H00FF : c++
outbuf[c] = &HFF : c++ 'ALL OUTPUT
FT_WAIT(1)
NUS_SetCtrlPin(NUS_RE)
FT_WAIT(15)
NUS_SetCtrlPin(NUS_WE or NUS_RE)
FT_WAIT(4)
End Sub
Function NUS_InitRomAccess(hFT As HANDLE) As BOOL
NUS_InitRomAccess = FT_InitRomAccess(hFT)
End Function
Enum NUS_JOYBUS_TYPE
NUS_JOYBUS_EEPROM
NUS_JOYBUS_CONTROLLER
End Enum
Function NUS_InitJoybusAccess(hFT As HANDLE, bus_type As NUS_JOYBUS_TYPE) As BOOL
if bus_type = NUS_JOYBUS_EEPROM then
NUS_InitJoybusAccess = FT_InitJoybusAccessEEPROM(hFT)
else
NUS_InitJoybusAccess = FT_InitJoybusAccessController(hFT)
endif
End Function
Enum NUS_JOYBUS_ERR
NUS_JOYBUS_OK = 0
NUS_JOYBUS_SEND_ERR
NUS_JOYBUS_RECEIVE_ERR
NUS_JOYBUS_LOGIC_ERR
NUS_JOYBUS_TIMEOUT
_NUS_JOYBUS_ERR_MAX
End Enum
Function NUS_JoybusErrorText(err As NUS_JOYBUS_ERR) As BytePtr
Dim tbl[_NUS_JOYBUS_ERR_MAX] = [
"NUS_JOYBUS_OK", _
"NUS_JOYBUS_SEND_ERR", _
"NUS_JOYBUS_RECEIVE_ERR", _
"NUS_JOYBUS_LOGIC_ERR", _
"NUS_JOYBUS_TIMEOUT", _
"_NUS_JOYBUS_ERR_MAX", _
] As BytePtr
NUS_JoybusErrorText = tbl[err]
End Function
Function NUS_JoybusCommand(cmd As BytePtr, cmdSize As Long, result As BytePtr, resultSize As Long) As NUS_JOYBUS_ERR
/*Dim dwab As DWord, i As DWord
Dim buf2[128] As Byte, readSize As DWord*/
' encode command
Dim cmd_enc As BufferClass, result_enc As BufferClass
if FT_JoybusEncode(cmd, cmdSize, cmd_enc) <> TRUE then
NUS_JoybusCommand = NUS_JOYBUS_LOGIC_ERR
exitfunction
endif
' Print "CMD"
' Dump(cmd_enc.ptr, cmd_enc.length())
Dim readSize As DWord, dwab As DWord
readSize = cmd_enc.length() + /* responce bytes */ resultSize*4+1
result_enc.alloc(readSize)
if FT_Write(hFT, cmd_enc.ptr, cmd_enc.length(), dwab) <> FT_OK then
NUS_JoybusCommand = NUS_JOYBUS_SEND_ERR
ExitFunction
endif
if FT_Read(hFT, result_enc.ptr, readSize, dwab) <> FT_OK then
NUS_JoybusCommand = NUS_JOYBUS_RECEIVE_ERR
ExitFunction
endif
result_enc.setLength(readSize)
if dwab <> readSize then
NUS_JoybusCommand = NUS_JOYBUS_TIMEOUT
ExitFunction
endif
FT_GetQueueStatus(hFT, readSize)
if readSize then
printf(ex"######### JoybusCommand: read leftover found. %d\n", readSize)
FT_Purge(hFT, FT_PURGE_RX or FT_PURGE_TX)
endif
' Dump(result_enc.ptr, result_enc.length())
if FT_JoybusDecode(result_enc.ptr+cmd_enc.length(), _
result_enc.length() - cmd_enc.length(), _
result, resultSize) <> TRUE then
NUS_JoybusCommand = NUS_JOYBUS_LOGIC_ERR
printf(ex"RAW JOYBUS RX DATA:\n")
Dump(result_enc.ptr, result_enc.length())
exitfunction
endif
NUS_JoybusCommand = NUS_JOYBUS_OK
End Function
Function NUS_JoybusGetControllerInput(result As BytePtr, resultSize As Long) As NUS_JOYBUS_ERR
' NUS_JoybusCommand(ex"\x08\x08\x08\xE8\x00", 5,
NUS_JoybusGetControllerInput = NUS_JoybusCommand(ex"\x01", 1, result, resultSize)
End Function
Type Align(1) NUS_JoybusDeviceInfo
id As Word
status As Byte
End Type
Function NUS_JoybusGetDeviceInfo(result As *NUS_JoybusDeviceInfo) As NUS_JOYBUS_ERR
NUS_JoybusGetDeviceInfo = NUS_JoybusCommand(ex"\x00", 1, result, sizeof(NUS_JoybusDeviceInfo))
End Function
Const NUS_JB_DEV_ID_CONTROLLER = &H0005
Const NUS_JB_DEV_ID_EEPROM_4K = &H8000
Const NUS_JB_DEV_ID_EEPROM_16K = &HC000
Function NUS_JoybusDeviceText(id As Word) As BytePtr
Select Case id
Case NUS_JB_DEV_ID_CONTROLLER
NUS_JoybusDeviceText = "Controller"
Case NUS_JB_DEV_ID_EEPROM_4K
NUS_JoybusDeviceText = "4 Kbit EEPROM"
Case NUS_JB_DEV_ID_EEPROM_16K
NUS_JoybusDeviceText = "16 Kbit EEPROM"
Case else
NUS_JoybusDeviceText = "unknown"
End Select
End Function
Function NUS_JoybusReadEEPROM(buf As *Byte, page As Byte) As NUS_JOYBUS_ERR
Dim cmdbuf[2] = [&H04, &H00] As Byte
cmdbuf[1] = page
NUS_JoybusReadEEPROM = NUS_JoybusCommand(cmdbuf, 2, buf, 8)
End Function