mirror of https://github.com/wwarthen/RomWBW.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
242 lines
6.1 KiB
242 lines
6.1 KiB
#include "ch376.h"
|
|
|
|
#include "ez80-helpers.h"
|
|
#include "print.h"
|
|
|
|
void ch_command(const uint8_t command) __z88dk_fastcall {
|
|
uint8_t counter = 255;
|
|
while ((CH376_COMMAND_PORT & PARA_STATE_BUSY) && --counter != 0)
|
|
;
|
|
|
|
// if (counter == 0) {
|
|
// It appears that the Ch376 has become blocked
|
|
// command will fail and timeout will eventually be returned by the ch_xxx_wait_int_and_get_status
|
|
// todo consider a return value to allow callers to respond appropriately
|
|
// Experimentation would indicate that USB_RESET_ALL will still work to reset chip
|
|
// return;
|
|
// }
|
|
|
|
CH376_COMMAND_PORT = command;
|
|
}
|
|
|
|
extern usb_error ch_wait_int_and_get_status(const int16_t timeout) __z88dk_fastcall;
|
|
|
|
usb_error ch_long_wait_int_and_get_status(void) { return ch_wait_int_and_get_status(5000); }
|
|
|
|
usb_error ch_short_wait_int_and_get_status(void) { return ch_wait_int_and_get_status(100); }
|
|
|
|
usb_error ch_very_short_wait_int_and_get_status(void) { return ch_wait_int_and_get_status(10); }
|
|
|
|
usb_error ch_get_status(void) {
|
|
ch_command(CH_CMD_GET_STATUS);
|
|
uint8_t ch_status = CH376_DATA_PORT;
|
|
|
|
if (ch_status >= USB_FILERR_MIN && ch_status <= USB_FILERR_MAX)
|
|
return ch_status;
|
|
|
|
if (ch_status == CH_CMD_RET_SUCCESS)
|
|
return USB_ERR_OK;
|
|
|
|
if (ch_status == CH_USB_INT_SUCCESS)
|
|
return USB_ERR_OK;
|
|
|
|
if (ch_status == CH_USB_INT_CONNECT)
|
|
return USB_INT_CONNECT;
|
|
|
|
if (ch_status == CH_USB_INT_DISK_READ)
|
|
return USB_ERR_DISK_READ;
|
|
|
|
if (ch_status == CH_USB_INT_DISK_WRITE)
|
|
return USB_ERR_DISK_WRITE;
|
|
|
|
if (ch_status == CH_USB_INT_DISCONNECT) {
|
|
ch_cmd_set_usb_mode(5);
|
|
return USB_ERR_NO_DEVICE;
|
|
}
|
|
|
|
if (ch_status == CH_USB_INT_BUF_OVER)
|
|
return USB_ERR_DATA_ERROR;
|
|
|
|
ch_status &= 0x2F;
|
|
|
|
if (ch_status == 0x2A)
|
|
return USB_ERR_NAK;
|
|
|
|
if (ch_status == 0x2E)
|
|
return USB_ERR_STALL;
|
|
|
|
ch_status &= 0x23;
|
|
|
|
if (ch_status == 0x20)
|
|
return USB_ERR_TIMEOUT;
|
|
|
|
if (ch_status == 0x23)
|
|
return USB_TOKEN_OUT_OF_SYNC;
|
|
|
|
return USB_ERR_UNEXPECTED_STATUS_FROM_HOST;
|
|
}
|
|
|
|
void ch_cmd_reset_all(void) { ch_command(CH_CMD_RESET_ALL); }
|
|
|
|
inline uint8_t ch_cmd_check_exist(void) {
|
|
uint8_t complement;
|
|
ch_command(CH_CMD_CHECK_EXIST);
|
|
CH376_DATA_PORT = (uint8_t)~0x55;
|
|
delay();
|
|
complement = CH376_DATA_PORT;
|
|
return complement == 0x55;
|
|
// if (complement != 0x55)
|
|
// return false;
|
|
|
|
// ch_command(CH_CMD_CHECK_EXIST);
|
|
// CH376_DATA_PORT = (uint8_t)~0x89;
|
|
// delay();
|
|
// complement = CH376_DATA_PORT;
|
|
// return complement == 0x89;
|
|
}
|
|
|
|
uint8_t ch_probe(void) {
|
|
uint8_t i = 5;
|
|
do {
|
|
if (ch_cmd_check_exist())
|
|
return true;
|
|
|
|
delay_medium();
|
|
} while (--i != 0);
|
|
|
|
return false;
|
|
}
|
|
|
|
usb_error ch_cmd_set_usb_mode(const uint8_t mode) __z88dk_fastcall {
|
|
uint8_t result = 0;
|
|
|
|
CH376_COMMAND_PORT = CH_CMD_SET_USB_MODE;
|
|
delay();
|
|
CH376_DATA_PORT = mode;
|
|
delay();
|
|
|
|
uint8_t count = 127;
|
|
|
|
while (result != CH_CMD_RET_SUCCESS && result != CH_CMD_RET_ABORT && --count != 0) {
|
|
result = CH376_DATA_PORT;
|
|
delay();
|
|
}
|
|
|
|
return (result == CH_CMD_RET_SUCCESS) ? USB_ERR_OK : USB_ERR_FAIL;
|
|
}
|
|
|
|
uint8_t ch_cmd_get_ic_version(void) {
|
|
ch_command(CH_CMD_GET_IC_VER);
|
|
return CH376_DATA_PORT & 0x1f;
|
|
}
|
|
|
|
void ch_issue_token(const uint8_t toggle_bit, const uint8_t endpoint, const ch376_pid pid) {
|
|
ch_command(CH_CMD_ISSUE_TKN_X);
|
|
CH376_DATA_PORT = toggle_bit;
|
|
CH376_DATA_PORT = endpoint << 4 | pid;
|
|
}
|
|
|
|
void ch_issue_token_in(const endpoint_param *const endpoint) __z88dk_fastcall {
|
|
ch_issue_token(endpoint->toggle ? 0x80 : 0x00, endpoint->number, CH_PID_IN);
|
|
}
|
|
|
|
void ch_issue_token_out(const endpoint_param *const endpoint) __z88dk_fastcall {
|
|
ch_issue_token(endpoint->toggle ? 0x40 : 0x00, endpoint->number, CH_PID_OUT);
|
|
}
|
|
|
|
void ch_issue_token_out_ep0(void) { ch_issue_token(0x40, 0, CH_PID_OUT); }
|
|
|
|
void ch_issue_token_in_ep0(void) { ch_issue_token(0x80, 0, CH_PID_IN); }
|
|
|
|
void ch_issue_token_setup(void) { ch_issue_token(0, 0, CH_PID_SETUP); }
|
|
|
|
usb_error ch_data_in_transfer(uint8_t *buffer, int16_t buffer_size, endpoint_param *const endpoint) {
|
|
uint8_t count;
|
|
usb_error result;
|
|
|
|
if (buffer_size == 0)
|
|
return USB_ERR_OK;
|
|
|
|
USB_MODULE_LEDS = 0x01;
|
|
do {
|
|
ch_issue_token_in(endpoint);
|
|
|
|
result = ch_long_wait_int_and_get_status();
|
|
CHECK(result);
|
|
|
|
endpoint->toggle = !endpoint->toggle;
|
|
|
|
count = ch_read_data(buffer);
|
|
|
|
if (count == 0) {
|
|
USB_MODULE_LEDS = 0x00;
|
|
return USB_ERR_DATA_ERROR;
|
|
}
|
|
|
|
buffer += count;
|
|
buffer_size -= count;
|
|
} while (buffer_size > 0);
|
|
|
|
USB_MODULE_LEDS = 0x00;
|
|
return USB_ERR_OK;
|
|
|
|
done:
|
|
USB_MODULE_LEDS = 0x00;
|
|
return result;
|
|
}
|
|
|
|
// TODO: review: does buffer_size need to be signed?
|
|
usb_error ch_data_in_transfer_n(uint8_t *const buffer, uint8_t *const buffer_size, endpoint_param *const endpoint) {
|
|
uint8_t count;
|
|
usb_error result;
|
|
|
|
USB_MODULE_LEDS = 0x01;
|
|
|
|
ch_issue_token_in(endpoint);
|
|
|
|
CHECK(ch_long_wait_int_and_get_status());
|
|
|
|
endpoint->toggle = !endpoint->toggle;
|
|
|
|
count = ch_read_data(buffer);
|
|
|
|
*buffer_size = count;
|
|
|
|
USB_MODULE_LEDS = 0x00;
|
|
|
|
return USB_ERR_OK;
|
|
done:
|
|
USB_MODULE_LEDS = 0x00;
|
|
return result;
|
|
}
|
|
|
|
usb_error ch_data_out_transfer(const uint8_t *buffer, int16_t buffer_length, endpoint_param *const endpoint) {
|
|
usb_error result;
|
|
const uint8_t number = endpoint->number;
|
|
const uint8_t max_packet_size = calc_max_packet_size(endpoint->max_packet_sizex);
|
|
|
|
USB_MODULE_LEDS = 0x02;
|
|
|
|
while (buffer_length > 0) {
|
|
const uint8_t size = max_packet_size < buffer_length ? max_packet_size : buffer_length;
|
|
buffer = ch_write_data(buffer, size);
|
|
buffer_length -= size;
|
|
ch_issue_token_out(endpoint);
|
|
|
|
CHECK(ch_long_wait_int_and_get_status());
|
|
|
|
endpoint->toggle = !endpoint->toggle;
|
|
}
|
|
|
|
USB_MODULE_LEDS = 0x00;
|
|
return USB_ERR_OK;
|
|
|
|
done:
|
|
USB_MODULE_LEDS = 0x00;
|
|
return result;
|
|
}
|
|
|
|
void ch_set_usb_address(const uint8_t device_address) __z88dk_fastcall {
|
|
ch_command(CH_CMD_SET_USB_ADDR);
|
|
CH376_DATA_PORT = device_address;
|
|
}
|
|
|