mirror of
https://github.com/dingusdev/dingusppc.git
synced 2026-04-19 10:20:36 +00:00
Cuda improvements
* Implements missing Cuda commands * Proper One Second Mode handling * Add Stat Response ADB bit * Typo fixes Co-Authored-By: Tim Jarzombek <tim@jarz.net>
This commit is contained in:
@@ -38,6 +38,7 @@ enum {
|
||||
ADB_STAT_SRQ_ACTIVE = 1 << 0,
|
||||
ADB_STAT_TIMEOUT = 1 << 1,
|
||||
ADB_STAT_AUTOPOLL = 1 << 6,
|
||||
ADB_STAT_RESPONSE = 1 << 7,
|
||||
};
|
||||
|
||||
class AdbDevice; // forward declaration to prevent compiler errors
|
||||
|
||||
+65
-24
@@ -64,7 +64,7 @@ ViaCuda::ViaCuda() : I2CBus() {
|
||||
this->_via_ifr = 0; // all flags cleared
|
||||
this->_via_ier = 0; // all interrupts disabled
|
||||
|
||||
// intialize counters/timers
|
||||
// initialize counters/timers
|
||||
this->t1_counter = 0xFFFF;
|
||||
this->t2_counter = 0xFFFF;
|
||||
|
||||
@@ -573,11 +573,11 @@ template void ViaCuda::append_data(uint16_t data);
|
||||
template void ViaCuda::append_data(uint32_t data);
|
||||
|
||||
void ViaCuda::process_adb_command() {
|
||||
uint8_t adb_stat, output_size;
|
||||
uint8_t adb_stat;
|
||||
|
||||
adb_stat = this->adb_bus_obj->process_command(&this->in_buf[1],
|
||||
this->in_count - 1);
|
||||
response_header(CUDA_PKT_ADB, adb_stat);
|
||||
response_header(CUDA_PKT_ADB, adb_stat | ADB_STAT_RESPONSE);
|
||||
this->append_data(this->adb_bus_obj->get_output_buf(), this->adb_bus_obj->get_output_count());
|
||||
}
|
||||
|
||||
@@ -587,6 +587,14 @@ void ViaCuda::autopoll_handler() {
|
||||
this->do_post_keyboard_state_events = false;
|
||||
}
|
||||
|
||||
// Don't send async packets while the host has TIP asserted - that
|
||||
// means an active byte transfer is in progress in either direction.
|
||||
// The real Cuda is single-threaded and would never enter its idle
|
||||
// loop during a transaction.
|
||||
if (!this->old_tip) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t poll_command = this->autopoll_enabled ? this->adb_bus_obj->poll() : 0;
|
||||
|
||||
if (poll_command) {
|
||||
@@ -595,7 +603,7 @@ void ViaCuda::autopoll_handler() {
|
||||
}
|
||||
|
||||
// prepare autopoll packet
|
||||
response_header(CUDA_PKT_ADB, ADB_STAT_OK | ADB_STAT_AUTOPOLL);
|
||||
response_header(CUDA_PKT_ADB, ADB_STAT_OK | ADB_STAT_AUTOPOLL | ADB_STAT_RESPONSE);
|
||||
this->out_buf[2] = poll_command; // put the proper ADB command
|
||||
this->append_data(this->adb_bus_obj->get_output_buf(), this->adb_bus_obj->get_output_count());
|
||||
|
||||
@@ -607,24 +615,40 @@ void ViaCuda::autopoll_handler() {
|
||||
schedule_sr_int(USECS_TO_NSECS(30));
|
||||
} else if (this->one_sec_mode != 0) {
|
||||
uint32_t this_time = calc_real_time();
|
||||
|
||||
// Don't send one-second packets if a command response is pending.
|
||||
// Unlike autopoll, time packets are not urgent enough to preempt.
|
||||
if (!this->treq || this->treq_timer_id) {
|
||||
// ERS: track missed ticks for mode $02/$03 fallback
|
||||
if (this_time != this->last_time)
|
||||
this->one_sec_missed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (this_time != this->last_time) {
|
||||
/*
|
||||
We'll send a time packet every 4
|
||||
seconds just in case we get out of
|
||||
sync.
|
||||
*/
|
||||
// ERS: first one-sec packet after mode change is always mode $01;
|
||||
// missed packets also fall back to mode $01.
|
||||
bool force_full = this->one_sec_first_pkt || this->one_sec_missed;
|
||||
bool send_time = !(this->last_time & 3);
|
||||
if (send_time || this->one_sec_mode < 3) {
|
||||
|
||||
if (force_full || send_time || this->one_sec_mode == 1) {
|
||||
// Mode $01 (or fallback): full header + 4-byte RTC
|
||||
response_header(CUDA_PKT_PSEUDO, 0);
|
||||
this->out_buf[2] = CUDA_GET_REAL_TIME;
|
||||
uint32_t real_time = this_time + this->time_offset;
|
||||
this->append_data(real_time);
|
||||
} else if (this->one_sec_mode == 2) {
|
||||
// Mode $02: header only (no time data)
|
||||
response_header(CUDA_PKT_PSEUDO, 0);
|
||||
this->out_buf[2] = CUDA_GET_REAL_TIME;
|
||||
if (send_time || this->one_sec_mode == 1) {
|
||||
uint32_t real_time = this_time + this->time_offset;
|
||||
this->append_data(real_time);
|
||||
}
|
||||
} else if (this->one_sec_mode == 3) {
|
||||
// Mode $03: truncated - attention + type only
|
||||
one_byte_header(CUDA_PKT_TICK);
|
||||
}
|
||||
this->last_time = this_time;
|
||||
|
||||
this->one_sec_first_pkt = false;
|
||||
this->one_sec_missed = false;
|
||||
this->last_time = this_time;
|
||||
|
||||
// assert TREQ
|
||||
this->via_portb &= ~CUDA_TREQ;
|
||||
@@ -638,11 +662,13 @@ void ViaCuda::autopoll_handler() {
|
||||
|
||||
void ViaCuda::disable_async_packets() {
|
||||
// disable autopolling of ADB devices
|
||||
this->autopoll_enabled = false;
|
||||
this->autopoll_enabled = false;
|
||||
this->do_post_keyboard_state_events = false;
|
||||
|
||||
// disable one second packets
|
||||
this->one_sec_mode = 0;
|
||||
this->one_sec_mode = 0;
|
||||
this->one_sec_first_pkt = true;
|
||||
this->one_sec_missed = false;
|
||||
}
|
||||
|
||||
void ViaCuda::pseudo_command() {
|
||||
@@ -672,7 +698,7 @@ void ViaCuda::pseudo_command() {
|
||||
this->cur_pram_addr = addr - CUDA_PRAM_START;
|
||||
this->next_out_handler = &ViaCuda::pram_out_handler;
|
||||
} else if (addr >= CUDA_ROM_START) {
|
||||
// HACK: Cuda ROM dump requsted so let's partially fake it
|
||||
// HACK: Cuda ROM dump requested so let's partially fake it
|
||||
this->append_data(uint8_t(0)); // empty copyright string
|
||||
this->append_data(uint16_t(0x0019U));
|
||||
this->append_data(uint16_t(CUDA_FW_VERSION_MAJOR));
|
||||
@@ -688,7 +714,7 @@ void ViaCuda::pseudo_command() {
|
||||
break;
|
||||
}
|
||||
case CUDA_WRITE_MCU_MEM:
|
||||
addr = READ_WORD_BE_A(&this->in_buf[2]);
|
||||
addr = READ_WORD_BE_U(&this->in_buf[2]);
|
||||
// if addr is inside PRAM, update PRAM with data from in_buf
|
||||
// otherwise, ignore data in in_buf
|
||||
if (addr >= CUDA_PRAM_START && addr <= CUDA_PRAM_END) {
|
||||
@@ -700,7 +726,7 @@ void ViaCuda::pseudo_command() {
|
||||
response_header(CUDA_PKT_PSEUDO, 0);
|
||||
break;
|
||||
case CUDA_READ_PRAM:
|
||||
addr = READ_WORD_BE_A(&this->in_buf[2]);
|
||||
addr = READ_WORD_BE_U(&this->in_buf[2]);
|
||||
if (addr <= 0xFF) {
|
||||
response_header(CUDA_PKT_PSEUDO, 0);
|
||||
// this command is open-ended so set up the corresponding context
|
||||
@@ -719,7 +745,7 @@ void ViaCuda::pseudo_command() {
|
||||
break;
|
||||
}
|
||||
case CUDA_WRITE_PRAM:
|
||||
addr = READ_WORD_BE_A(&this->in_buf[2]);
|
||||
addr = READ_WORD_BE_U(&this->in_buf[2]);
|
||||
if (addr <= 0xFF) {
|
||||
// transfer data from in_buf to PRAM
|
||||
for (i = 0; i < this->in_count - 4; i++) {
|
||||
@@ -760,6 +786,7 @@ void ViaCuda::pseudo_command() {
|
||||
case CUDA_ONE_SECOND_MODE:
|
||||
LOG_F(INFO, "Cuda: One Second Interrupt Mode: %d", this->in_buf[2]);
|
||||
this->one_sec_mode = this->in_buf[2];
|
||||
this->one_sec_first_pkt = true;
|
||||
response_header(CUDA_PKT_PSEUDO, 0);
|
||||
break;
|
||||
case CUDA_SET_POWER_MESSAGES:
|
||||
@@ -795,11 +822,25 @@ void ViaCuda::pseudo_command() {
|
||||
power_on = false;
|
||||
power_off_reason = po_shut_down;
|
||||
break;
|
||||
case CUDA_SET_POWER_UPTIME: {
|
||||
uint32_t alarm_time = READ_DWORD_BE_U(&this->in_buf[2]);
|
||||
LOG_F(INFO, "Cuda: Set Power-Up Alarm to 0x%08X", alarm_time);
|
||||
response_header(CUDA_PKT_PSEUDO, 0);
|
||||
break;
|
||||
}
|
||||
case CUDA_WARM_START:
|
||||
LOG_F(INFO, "Cuda: Warm Start - disabling async packets");
|
||||
this->disable_async_packets();
|
||||
response_header(CUDA_PKT_PSEUDO, 0);
|
||||
break;
|
||||
case CUDA_MONO_STABLE_RESET:
|
||||
/* really kludge temp code */
|
||||
LOG_F(INFO, "Cuda: Restart/Shutdown signal sent with command 0x%x!", cmd);
|
||||
//exit(0);
|
||||
this->mono_stable = !!this->in_buf[2];
|
||||
LOG_F(INFO, "Cuda: Monostable Reset %s", this->mono_stable ? "set" : "cleared");
|
||||
response_header(CUDA_PKT_PSEUDO, 0);
|
||||
break;
|
||||
case CUDA_TOGGLE_WAKEUP:
|
||||
LOG_F(INFO, "Cuda: Toggle Wakeup");
|
||||
response_header(CUDA_PKT_PSEUDO, 0);
|
||||
break;
|
||||
default:
|
||||
LOG_F(ERROR, "Cuda: unsupported pseudo command 0x%X", cmd);
|
||||
|
||||
@@ -67,7 +67,7 @@ enum {
|
||||
VIA_T2CH = 0x09, // high-order timer 2 counter
|
||||
VIA_SR = 0x0A, // shift register
|
||||
VIA_ACR = 0x0B, // auxiliary control register
|
||||
VIA_PCR = 0x0C, // periheral control register
|
||||
VIA_PCR = 0x0C, // peripheral control register
|
||||
VIA_IFR = 0x0D, // interrupt flag register
|
||||
VIA_IER = 0x0E, // interrupt enable register
|
||||
VIA_ANH = 0x0F, // input/output register A, no handshake
|
||||
@@ -135,7 +135,7 @@ enum {
|
||||
CUDA_ONE_SECOND_MODE = 0x1B, // one second interrupt mode
|
||||
CUDA_SET_POWER_MESSAGES = 0x21, // set power message flag
|
||||
CUDA_READ_WRITE_I2C = 0x22, // read/write I2C
|
||||
CUDE_TOGGLE_WAKEUP = 0x23, // toggle wake-up
|
||||
CUDA_TOGGLE_WAKEUP = 0x23, // toggle wake-up
|
||||
CUDA_TIMER_TICKLE = 0x24, // set timer tickle
|
||||
CUDA_COMB_FMT_I2C = 0x25, // combined format I2C transaction
|
||||
CUDA_OUT_PB0 = 0x26, // output one bit to Cuda's PB0 line
|
||||
@@ -190,7 +190,7 @@ private:
|
||||
uint8_t via_porta = 0;
|
||||
uint8_t via_ddrb = 0;
|
||||
uint8_t via_ddra = 0;
|
||||
uint8_t via_sr;
|
||||
uint8_t via_sr = 0;
|
||||
uint8_t via_acr = 0;
|
||||
uint8_t via_pcr = 0;
|
||||
|
||||
@@ -231,18 +231,22 @@ private:
|
||||
int max_in_count = 0;
|
||||
uint8_t out_buf[16];
|
||||
int32_t out_count;
|
||||
int32_t out_pos;
|
||||
int32_t out_pos = 0;
|
||||
uint8_t poll_rate;
|
||||
uint32_t last_time = 0;
|
||||
uint32_t time_offset = 0;
|
||||
std::chrono::time_point<std::chrono::system_clock> mac_epoch;
|
||||
uint8_t one_sec_mode = 0;
|
||||
bool file_server;
|
||||
bool one_sec_first_pkt = true; // ERS: first one-sec pkt always mode $01
|
||||
bool one_sec_missed = false; // ERS: missed pkt -> fallback to mode $01
|
||||
bool file_server = false;
|
||||
bool mono_stable = false;
|
||||
uint8_t ipl_level = 0;
|
||||
uint16_t device_mask = 0;
|
||||
|
||||
bool is_open_ended; // true if current transaction is open-ended
|
||||
uint8_t curr_i2c_addr; // current I2C address
|
||||
uint8_t cur_pram_addr; // current PRAM address, range 0...FF
|
||||
bool is_open_ended = false; // true if current transaction is open-ended
|
||||
uint8_t curr_i2c_addr = 0; // current I2C address
|
||||
uint8_t cur_pram_addr = 0; // current PRAM address, range 0...FF
|
||||
|
||||
void (ViaCuda::*out_handler)(void);
|
||||
void (ViaCuda::*next_out_handler)(void);
|
||||
|
||||
Reference in New Issue
Block a user