And straight to the point!
The Maple BUS protocol is symmetric, that is, having one good implementation, for example HOST, the same implementation can be used as DEVICE. Easier - you can read the joystick, or you can pretend to be it.
Protocol description (hardware)
The Maple BUS interface is two-wire. SDCKA / SDCKB, each of the lines at certain stages plays the role of both "transmitting data" and "latching data".
Communication on the Maple BUS is carried out in packages. Each data packet consists of a header pattern, data, checksum, and a trailing pattern. The maximum data packet length is 1024 bytes.
There are 5 types of patterns in total:
START - indicates the start of data transmission (4-reklok SDCKB while SDCKA is at a low level).
The package should always end with the END pattern (2 clocks of SDCKA while SDCKB is at a low level):
Occupancy - (8- SDCKB SDCKA ). HI->LO SDCKA , LO->HI . (Light GUN - Func. FT7):
RESET - (14- SDCKB SDCKA , DEVICE).
.
. - SDCKB, - SDCKA, ( :) ).
1:
, VMU, , ...
Maple BUS Device, Device Expansion Device, Device Expansion Device LM-Bus. Expansion 5-, , ( 315-6211-AB) " " 2- ( EXP-DEV , , VMU LCD , Exp. ).
LM-BUS Maple BUS, DEVICE Maple BUS Exp. DEVICE HOST'.
LM-BUS , , .
, :
COMMAND - , 0x01 0xFE (. "maplebus.h").
maplebus commands
//HOST
#define DeviceRequest 0x01
#define AllStatusRequest 0x02
#define DeviceReset 0x03
#define DeviceKill 0x04
#define GetCondition 0x09
#define GetMediaInfo 0x0A
#define BlockRead 0x0B
#define BlockWrite 0x0C
#define GetLastError 0x0D
#define SetCondition 0x0E
#define FT4Control 0x0F
#define ARControl 0x10
#define TransmitAgain 0xFC
//Device
#define DeviceStatus 0x05
#define DeviceAllStatus 0x06
#define DeviceReply 0x07
#define DataTransfer 0x08
#define ARError 0xF9
#define LCDError 0xFA
#define FileError 0xFB
#define TransmitAgain 0xFC
#define CommandUnknown 0xFD
#define FunctionTypeUnknown 0xFE
DEST. AP - ( ).
ORIG. AP - .
AP :
PO[1:0] - (A - 00, B - 01, C - 10, D - 11).
D/E - (1 - Device, 0 - Expansion Device PORT).
LM[4:0] - (1 - Exp. DEVICE , 0 - Exp. ).
DATA SIZE - 32- .
DATA - .
CRC - XOR COMMAND, AP, DATA SIZE, DATA.
"" HOST DEVICE DeviceRequest, , , "" (A/B/C/D).
(DeviceStatus answer):
Device ID - (Device ID FT, FD - ).
Device Functions
/*Device functions*/
#define CONTROLLER MAKE_DWORD(0x00000001) //FT0 : Controller Function
#define STORAGE MAKE_DWORD(0x00000002) //FT1 : Storage Function
#define LCD MAKE_DWORD(0x00000004) //FT2 : B/W LCD Function
#define TIMER MAKE_DWORD(0x00000008) //FT3 : Timer Function
#define AUDIO_INPUT MAKE_DWORD(0x00000010) //FT4 : Audio input device Function
#define AR_GUN MAKE_DWORD(0x00000020) //FT5 : AR-Gun Function
#define KEYBOARD MAKE_DWORD(0x00000040) //FT6 : Keyboard
#define GUN MAKE_DWORD((unsigned int)0x00000080) //FT7 : Light-Gun Function
#define VIBRATION MAKE_DWORD((unsigned int)0x00000100) //FT8 : Vibration Function
#define MOUSE MAKE_DWORD((unsigned int)0x00000200) //FT9 : Pointing Function
#define EXMEDIA MAKE_DWORD((unsigned int)0x00000400) //FT10 : Exchange Media Function
#define CAMERA MAKE_DWORD((unsigned int)0x00000800) //FT11 : Camera Device Functio
Destination code - .
Product name - ( {'D','r','e','a','m','c','a','s','t',' ','C','o','n','t','r','o','l','l','e','r', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' '} - 30 ).
License - ( {'P','r','o','d','u','c','e','d',' ','B','y',' ','o','r',' ','U','n','d','e','r',' ','L','i','c','e','n','s','e',' ','F','r','o','m',' ','S','E','G','A',' ','E','N','T','E','R','P','R','I','S','E','S',',','L','T','D','.',' ',' ',' ',' ',' ',} -60 ).
Min./Max. current - . (1 = 10 , 43 => 0x1AE).
" " ( , ), : 40 "Version 1.000,1998/05/11,315-6125-AB Analog Module: The 4th Edition. 05/08".
, Device ID.
FT0, CONTROLLER, GetCondition - / . Device ID. , Device ID :
GetCondition, , :
Ra/La/Da/Ua - /// ( "").
Start/A/B/X/Y - .
A1, A2 -
A3 A4 - "".
.
( )
SDCKA SDCKB , , , , " " , , " " , , .
CPLD (EPM3032) xMAPLE:
SDCKA/SDCKB - Maple BUS.
GCLK - CLK 16-48MHz.
INHTxD - , 1 - , 0 - .
RxD - .
nSTRCV- (Rising Edge).
nDLatch - " " ( Q[7..0] ).
Q[7..0] - .
EOP - END ( ).
FERR - .
nRST - - RESET , - 0.
:
' (3 , ):
SMAPLE.v
module SMAPLE(
input GCLK, //MCU Generated 16MHz clock input
input INHTxD, //Inhibit Input Data (User Can disable XMAPLE Detect Signals While MCU Transmit DATA)
input SDCKAi, //Data/Clock A Line
input SDCKBi, //Data/Clock B Line
output RxD, //Receive on progress (While receive is 1)
output [7:0]Q // Output data bus (MCU can read valid data on this
//port in time 200uS after data latch Negative Pulse received)
, output nSTRCV, //Receive start, negative pulse - Output
output OCPYi, //Occupancy packet received - Output
output nRST, //Reset packet received - Output
output FERR, //Frame error - Output
output EOPi, //End Of Packed received - Output
output nDLatch //New Data latched on BUS (Negative Pulse)
);
/*Control Register*/
reg rRxD = 0;
assign RxD = rRxD;
reg rFERR = 0;
assign FERR = rFERR;
wire nWE;
assign nDLatch = (EOPi & nWE);
wire iFERR;
/* Align Data Packet */
reg rENA = 1'b0;
reg rENB = 1'b0;
always @(posedge GCLK or negedge nRST) begin
if(!nRST) begin
rENA <= 1'b0;
rENB <= 1'b0;
end else begin
rENA <= SDCKAi;
rENB <= SDCKBi;
end
end
always @(posedge GCLK or negedge nRST) begin
if(!nRST) begin
rFERR <= 0;
rRxD <= 0;
end else begin
if(!EOPi)// && !INHTxD)
rRxD <=0 ;
else begin
if(!iFERR) rFERR <= 1;
if(!nSTRCV) begin
rFERR <= 0;
rRxD <= ~INHTxD;
end
end
end
end
line_monitor line_monitor
(
.GCLK(GCLK), //Global Clock - Input
.SDCKA(SDCKAi|INHTxD), //CLOCK/DATA Line A disabled by data transmit - Input
.SDCKB(SDCKBi|INHTxD), //CLOCK/DATA Line B disabled by data transmit - Input
.RxDr(RxD), //Data Receive in progress - Input
.RxD(nSTRCV), //Receive start, negative pulse - Output
.OCPY(OCPYi), //Occupancy packet received - Output
.RESET(nRST), //Reset packet received - Output
.FERR(iFERR), //Frame error - Output
.EOP(EOPi), //End Of Packed received - Output
.ENA(rENA), //CLOCK For Line B
.ENB(rENB) //CLOCK For Line A
);
/*Receive Maple Frame*/
maple_receive maple_receive
(
.SDCKA(SDCKAi), //CLOCK/DATA Line A disabled by data transmit - Input
.SDCKB(SDCKBi), //CLOCK/DATA Line B disabled by data transmit - Input
.ENA(rENA), //CLOCK For Line B
.ENB(rENB), //CLOCK For Line A
.RCV(RxD), //Receive in progress, 1 - receive - Input
.Dout(Q[7:0]), //Received data byte - Output
.nWE(nWE), //Write Latch - Output
.RxDi(nSTRCV), //Receive start, negative pulse - Input
.INHTxD(INHTxD) //Inhibit Input Data (User Can disable XMAPLE Detect Signals While MCU Transmit DATA)
);
endmodule
line_monitor.v
module line_monitor
(
input GCLK,
input SDCKA,
input SDCKB,
input RxDr, //Data Receive in progress - Input
output RxD,
output OCPY,
output RESET,
output FERR,
output EOP,
input ENA,
input ENB
);
reg [3:0] countA = 0;
reg [2:0] countB = 0;
reg [3:0] pcount = 0;
reg rEOP = 1'b1;
assign EOP = rEOP;
assign RxD = (pcount == 4'h4) ? 1'b0 : 1'b1;
assign OCPY = (pcount == 4'h8) ? 1'b0 : 1'b1;
assign RESET = (pcount == 4'hE)? 1'b0 : 1'b1; //Output reset signal does not need to check for FERR
assign FERR = (!((RxD & OCPY & RESET) && pcount[3:1])) | (!RxDr & !rEOP);
//assign EOP = (eopcount == 3'h2) ? 1'b0 : 1'b1;
always @(posedge SDCKA) pcount <= countA;
always @(posedge SDCKB) rEOP <= !(countB == 3'h2);
//Patterns
//PATTERN Counter Managing
always @(posedge ENA or negedge ENB) begin
if (ENA) begin
countA <= 0;
end
else begin
countA <= countA + 4'h1;
end
end
//EOP Counter Managing
always @(posedge ENB or negedge ENA) begin
if (ENB) begin
countB <= 0;
end
else begin
countB <= countB + 3'h1;
end
end
//synopsys translate_off
//synopsys translate_on
endmodule
maple_receive.v
module maple_receive
(
input SDCKA, //CLOCK/DATA Line A
input SDCKB, //CLOCK/DATA Line B
input ENA, //CLOCK
input ENB, //CLOCK
input RCV, //Receive in progress, 1 - valid
output [7:0]Dout, //received data output
output nWE,
input RxDi,
input INHTxD //Inhibit Input Data (User Can disable XMAPLE Detect Signals While MCU Transmit DATA)
);
reg [3:0] dataA = 4'h0;
reg [3:0] dataB = 4'h0;
reg [1:0]countB = 2'b00;
reg rLastBitCounted = 1'b1;
//B LINE
//Dout[1] = SDCKA Means Major version 1.
//Dout[0] = SDCKB Means Minor version .0
//And version result = 1.0
assign Dout[1] = !INHTxD ? dataB[0] : SDCKA;
assign Dout[3] = dataB[1];
assign Dout[5] = dataB[2];
assign Dout[7] = dataB[3];
//A LINE
assign Dout[0] = !INHTxD ? dataA[0] : SDCKB;
assign Dout[2] = dataA[1];
assign Dout[4] = dataA[2];
assign Dout[6] = dataA[3];
assign nWE = (dtaLock);
always @(negedge ENA)begin
dataB[3:1] <= dataB[2:0];
dataB[0] <= SDCKB;
if(RCV) begin
countB <= countB + 2'b1;
end else begin
countB <= 2'b11;
end
end
always @(negedge ENB)begin
dataA[3:1] <= dataA[2:0];
dataA[0] <= SDCKA;
rLastBitCounted <= !countB[0] | !countB[1];
end
wire dtaLock = rLastBitCounted;
endmodule
" " Eval Board.
:
:
Eval...
:
, , .
Dreamcast XBOX360 ( " " XBOX360, ).
, , :
, "".
SD - :
... USB HID, MAPLE.
:
USE_STDPERIPH_DRIVER - ST.
STM32F10X_MD - Medium Density.
MAPLE_HOST - MAPLE HOST.
USB_HID - HID .
, :
… ( Microsoft Xbox 360 Accessories, XInput... , ):
xMAPLE ...
DREAMCAST.
, - FT9 : Pointing Function.
, DeviceID GetCondition, .
Mouse DeviceID:
Dreamcast 3 : A,B,W, X/Y: AC1,AC2 (ball) "": AC3 (wheel).
AC1,AC2,AC3 - - .
:
AOV2, AOV1, AOV0 - AC3, AC2, AC1 .
PS/2 :
..., gerber'...
:
, , , .
"" :
( ) :
USE_STDPERIPH_DRIVER - ST.
STM32F10X_MD - Medium Density.
MAPLE_DEVICE - MAPLE DEVICE.
EN_MOUSE - HID .
MOUSE_CALLBACK - HOST.
EXTI9_5_CALLBACK - EXTI5-EXTI9 MAPLE_BUS.
(, HEX).
, EN_MOUSE EN_CONTROLLER, , PS/2 DREAMCAST, , DREAMCAST . "HALF LIFE " EN_CONTROLLER PS/2.
, DREAMCAST !!!
That's actually all I wanted to tell. However, I did not talk about (I hope I will tell you more :)):
How to work with VibroPAK.
How to implement a Memory Unit (although you can install and work with memory on the PS / 2 SPI EEPROM expansion board).
And I still have sets of printed circuit boards, and I can send three sets of printed circuit boards for the cost of mail to three who want to "try my hand".
Have a good day! Great mood and mutual understanding !!!