📄 minhost.c
字号:
// minhost.c
#define BYTE unsigned char
// SL811 Registers
#define CTL 0x00 // write this register to kick off a transfer
#define BUFADR 0x01 // start of internal data buffer
#define BUFLEN 0x02 // length of internal buffer
#define PID_EP 0x03 // name when written--PID and Endpoint for next xfr
#define PKTSTAT 0x03 // name when read--status of last transfer
#define FNADDR 0x04 // name when written--USB function address
#define CTL1 0x05 // more control stuff
#define INTSTATUS 0x0D // Interrupt request status bits. We use DONE and SOF.
#define SOFCT_L 0x0E // SOF (EOP) time constant low byte
#define SOFCT_H 0x0F // name when written--EOP time constant high byte
#define IN_PID 0x90 // PID (Packet ID) constants
#define SETUP_PID 0xD0 // for the 'set address' request
#define SOF_PID 0x05
// constants for 811 CTL1 register
#define USB_RESET 0x08 // SIERES=1
#define USB_OPERATE 0x21 // Low Speed=1(b5),SOF(EOP)EN=1(b0)
// use an 8051 port bit to sync transfers on oscilloscope
#define SCOPE_LO OUTA=0x00;
#define SCOPE_HI OUTA=0x01;
// EZ-USB registers
xdata BYTE SL811_ADDR _at_ 0x4000;
xdata BYTE SL811_DATA _at_ 0x4001;
xdata BYTE PORTACFG _at_ 0x7F93;
xdata BYTE OUTB _at_ 0x7F97;
xdata BYTE OEB _at_ 0x7F9D;
xdata BYTE PORTCCFG _at_ 0x7F95;
xdata BYTE OEA _at_ 0x7F9C;
xdata BYTE OUTA _at_ 0x7F96;
xdata BYTE I2CS _at_ 0x7FA5;
xdata BYTE I2DAT _at_ 0x7FA6;
// lookup table for EZ-USB Dev Board 7-segment readout
char digit[]={0x7f,0xad,0x9c,0xbf,0xa3,0x86,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x98,0xc0,0xa1};
// function prototypes
void wr811(BYTE address, BYTE value);
BYTE rd811(BYTE address);
void delay(tc);
BYTE go(BYTE cmd); // arm an 811 transfer, wait for completion, return status
void waitframes(BYTE num); // wait this many 1 msec frames
void display_hex (char val);
//***************************************************************************
void main(void)
{
BYTE result;
// set up the EZ-USB chip to talk to the 811 chip and provide scope trigger
PORTCCFG = 0xC0; // enable RD, WR pins
OEB = 0x03; // PB0 is SL811 RESET, PB1 is Host/Slave pin)
OEA = 0x01; // PA0 is scope trigger
SCOPE_LO; // initialize scope trigger
// Reset the SL811H chip
OUTB = 0x00; // PB1=0 means we're the host
delay(1000);
OUTB = 0x01; // remove reset, keep PB1 LOW for SLAVE
// SL811 initialization
wr811(BUFADR,0x10); // start of SETUP/IN internal data buffer
wr811(BUFLEN,0x08); // reserve 8 bytes
// (1) Reset the USB device. This makes it listen to address 0.
wr811(CTL1,USB_RESET); // Speed=1(L), JKFORCE=1, SOFEN=1
delay(10000); // about 18 milliseconds
wr811(CTL1,USB_OPERATE);
// Enable sending 1 msec EOP's (the low-speed version of SOF's)
wr811(SOFCT_L, 0xE0); // Set the SOF generator time constant
wr811(SOFCT_H, 0x2E | 0xC0); // 1 msec SOF rate, b7=HOST, b6=POLSWAP
// (2) Issue a SET_ADDRESS USB request, setting the peripheral address to 1
// From the USB spec, Chapter 9, here is the data for a "SET_ADDRESS" request:
// Note: every SL811_DATA load increments an internal SL811 address pointer
SL811_ADDR = 0x10; // next SL811_DATA byte goes here
SL811_DATA = 0x00; // bmRequestType (h->d,std request,device is recipient)
SL811_DATA = 0x05; // bRequest (SET_ADDRESS)
SL811_DATA = 0x01; // wValueL (device address)--we're setting it to ONE
SL811_DATA = 0x00; // wValueH (zero)
SL811_DATA = 0x00; // wIndexL (zero)
SL811_DATA = 0x00; // wIndexH (zero)
SL811_DATA = 0x00; // wLengthL (zero)
SL811_DATA = 0x00; // wLengthH (zero)
wr811(FNADDR,0x00); // USB address zero
wr811(PID_EP,SETUP_PID | 0x00); // SETUP PID, EP0
result=go(0x07); // DIREC=1(out), ENAB=1, ARM=1
// STATUS stage is a no-data IN to EP0
wr811(PID_EP,IN_PID | 0x00); // IN PID, EP0
result=go(0x03); // Don't sync to SOF, DIREC=0(in), ENAB, ARM
// (3) Send a CONTROL transfer to select configuration #1. Until we do this
// the device is in an "unconfigured" state and probably won't send data.
// Again, from USB spec Chapter 9:
SL811_ADDR = 0x10; // reset pointer to beginning of internal buffer.
SL811_DATA = 0x00; // bmRequestType (h->d,std request,device is recipient)
SL811_DATA = 0x09; // bRequest (SET_CONFIGURATION)
SL811_DATA = 0x01; // wValueL (configuration = 1)
SL811_DATA = 0x00; // wValueH (zero)
SL811_DATA = 0x00; // wIndexL (zero)
SL811_DATA = 0x00; // wIndexH (zero)
SL811_DATA = 0x00; // wLengthL (zero)
SL811_DATA = 0x00; // wLengthH (zero)
wr811(FNADDR,0x01); // now talking to USB device at address 1
wr811(PID_EP,SETUP_PID | 0x00); // OR in the endpoint (zero)
result=go(0x07); // DIREC=1(out), ENAB=1, ARM=1
// STATUS stage is a no-data IN to EP0
wr811(PID_EP,IN_PID | 0x00); // IN PID, EP0
result=go(0x03); // DIREC=0(in), ENAB=1, ARM=1
// (4) Send constant IN requests to Addr 1, EP1
wr811(PID_EP,IN_PID | 0x01); // set up for IN PIDS to endpoint 1
while(1)
{
SL811_ADDR = 0x10; // reset pointer to beginning of internal bufferf
waitframes(4); // send the IN requests every n milliseconds
result=go(0x03); // DIREC=0(in), ENAB=1, ARM=1
if (result & 0x01) // look only for ACK
display_hex(rd811(0x12)); // KB value is in third byte of 3-byte packet
}
} // end main
// *************************************************************************************
BYTE go(BYTE cmd) // Launch an 811 operation.
{
SCOPE_HI;
wr811(INTSTATUS,0x01); // clear the DONE bit
wr811(CTL,cmd); // start the operation
delay(100);
while(rd811(INTSTATUS) & 0x01 == 0){} // spin while "done" bit is low
SCOPE_LO;
return rd811(PKTSTAT); // return the status of this transfer
}
void waitframes(BYTE num)
{
int j;
BYTE result;
j=0;
while (j < num)
{
wr811(INTSTATUS,0xFF); // clear the int request flags
while (1)
{
result = (rd811(INTSTATUS)); // hang while SOF flag low
result &= 0x10; // SOF flag is bit 4
if (result == 0x10) break;
}
j++;
}
delay(100);
}
void wr811(BYTE address, BYTE value)
{
SL811_ADDR = address;
SL811_DATA = value;
}
BYTE rd811(BYTE address)
{
SL811_ADDR = address;
return SL811_DATA;
}
void delay(tc)
{
int timer;
timer = tc;
while(timer--){}
}
void display_hex (char val) // display one hex digit (over i2c bus)
{
if (val==00) val=0xFF; // blank display for key-up code (00)
else if (val==0x2A) val=0x7F; // backspace key is 0x2A (show decimal point)
else val = digit[val-0x53]; // all other keycodes fit into table values 0x53-0x63
while (I2CS & 0x40); // wait for STOP bit LOW--last operation complete
I2CS = 0x80; // set the START bit
I2DAT = 0x42; // IO expander address=42, LSB=0 for write
while ((I2CS & 0x01)!=0x01);// wait for DONE=1 (i2c transmit complete)
I2DAT = val; // send the data byte
while ((I2CS & 0x01)!=0x01);// wait for DONE=1
I2CS = 0x40; // set the STOP bit
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -