I2C overhaul part 6: making DDC actually work
This commit is contained in:
@@ -126,7 +126,7 @@ i2c_eeprom_init(void *i2c, uint8_t addr, uint8_t *data, uint32_t size, uint8_t w
|
||||
dev->addr_len = (size >= 4096) ? 16 : 8; /* use 16-bit addresses on 24C32 and above */
|
||||
dev->addr_mask = size - 1;
|
||||
|
||||
i2c_sethandler(i2c, dev->addr & ~(dev->addr_mask >> dev->addr_len), (dev->addr_mask >> dev->addr_len) + 1, i2c_eeprom_start, i2c_eeprom_read, i2c_eeprom_write, NULL, dev);
|
||||
i2c_sethandler(dev->i2c, dev->addr & ~(dev->addr_mask >> dev->addr_len), (dev->addr_mask >> dev->addr_len) + 1, i2c_eeprom_start, i2c_eeprom_read, i2c_eeprom_write, NULL, dev);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ enum {
|
||||
typedef struct {
|
||||
char *bus_name;
|
||||
void *i2c;
|
||||
uint8_t scl, sda, state, slave_state, slave_addr,
|
||||
uint8_t scl, sda, receive_wait_sda, state, slave_state, slave_addr,
|
||||
slave_read, last_sda, pos, transmit, byte;
|
||||
} i2c_gpio_t;
|
||||
|
||||
@@ -188,11 +188,12 @@ i2c_gpio_set(void *dev_handle, uint8_t scl, uint8_t sda)
|
||||
{
|
||||
i2c_gpio_t *dev = (i2c_gpio_t *) dev_handle;
|
||||
|
||||
i2c_gpio_log(3, "I2C GPIO %s: scl=%d->%d sda=%d->%d last_valid_sda=%d state=%d\n", dev->bus_name, dev->scl, scl, dev->last_sda, sda, dev->sda, dev->state);
|
||||
|
||||
switch (dev->state) {
|
||||
case I2C_IDLE:
|
||||
/* dev->scl check breaks NCR SDMS. */
|
||||
if (scl && dev->last_sda && !sda) { /* start bit */
|
||||
i2c_gpio_log(2, "I2C GPIO %s: Start bit received (from IDLE)\n", dev->bus_name);
|
||||
if (scl && dev->last_sda && !sda) { /* start condition; dev->scl check breaks NCR SDMS */
|
||||
i2c_gpio_log(2, "I2C GPIO %s: Start condition received (from IDLE)\n", dev->bus_name);
|
||||
dev->state = I2C_RECEIVE;
|
||||
dev->pos = 0;
|
||||
}
|
||||
@@ -201,6 +202,8 @@ i2c_gpio_set(void *dev_handle, uint8_t scl, uint8_t sda)
|
||||
case I2C_RECEIVE_WAIT:
|
||||
if (!dev->scl && scl)
|
||||
dev->state = I2C_RECEIVE;
|
||||
else if (!dev->scl && !scl && dev->last_sda && sda) /* workaround for repeated start condition on Windows XP DDC */
|
||||
dev->receive_wait_sda = 1;
|
||||
/* fall-through */
|
||||
|
||||
case I2C_RECEIVE:
|
||||
@@ -213,12 +216,12 @@ i2c_gpio_set(void *dev_handle, uint8_t scl, uint8_t sda)
|
||||
if (++dev->pos == 8)
|
||||
dev->state = i2c_gpio_write(dev);
|
||||
} else if (dev->scl && scl) {
|
||||
if (sda && !dev->last_sda) { /* stop bit */
|
||||
i2c_gpio_log(2, "I2C GPIO %s: Stop bit received (from RECEIVE)\n", dev->bus_name);
|
||||
if (sda && !dev->last_sda) { /* stop condition */
|
||||
i2c_gpio_log(2, "I2C GPIO %s: Stop condition received (from RECEIVE)\n", dev->bus_name);
|
||||
dev->state = I2C_IDLE;
|
||||
i2c_gpio_stop(dev);
|
||||
} else if (!sda && dev->last_sda) { /* start bit */
|
||||
i2c_gpio_log(2, "I2C GPIO %s: Start bit received (from RECEIVE)\n", dev->bus_name);
|
||||
} else if (!sda && dev->last_sda) { /* start condition */
|
||||
i2c_gpio_log(2, "I2C GPIO %s: Start condition received (from RECEIVE)\n", dev->bus_name);
|
||||
dev->pos = 0;
|
||||
dev->slave_state = SLAVE_IDLE;
|
||||
}
|
||||
@@ -229,6 +232,7 @@ i2c_gpio_set(void *dev_handle, uint8_t scl, uint8_t sda)
|
||||
if (!dev->scl && scl) {
|
||||
i2c_gpio_log(2, "I2C GPIO %s: Acknowledging transfer to %02X\n", dev->bus_name, dev->slave_addr);
|
||||
sda = 0;
|
||||
dev->receive_wait_sda = 0; /* ack */
|
||||
dev->pos = 0;
|
||||
dev->state = (dev->transmit == TRANSMITTER_MASTER) ? I2C_RECEIVE_WAIT : I2C_TRANSMIT;
|
||||
}
|
||||
@@ -261,13 +265,13 @@ i2c_gpio_set(void *dev_handle, uint8_t scl, uint8_t sda)
|
||||
|
||||
case I2C_TRANSMIT_WAIT:
|
||||
if (dev->scl && scl) {
|
||||
if (dev->last_sda && !sda) { /* start bit */
|
||||
if (dev->last_sda && !sda) { /* start condition */
|
||||
i2c_gpio_next_byte(dev);
|
||||
dev->pos = 0;
|
||||
i2c_gpio_log(2, "I2C GPIO %s: Next byte = %02X\n", dev->bus_name, dev->byte);
|
||||
}
|
||||
if (!dev->last_sda && sda) { /* stop bit */
|
||||
i2c_gpio_log(2, "I2C GPIO %s: Stop bit received (from TRANSMIT_WAIT)\n", dev->bus_name);
|
||||
if (!dev->last_sda && sda) { /* stop condition */
|
||||
i2c_gpio_log(2, "I2C GPIO %s: Stop condition received (from TRANSMIT_WAIT)\n", dev->bus_name);
|
||||
dev->state = I2C_IDLE;
|
||||
i2c_gpio_stop(dev);
|
||||
}
|
||||
@@ -277,8 +281,8 @@ i2c_gpio_set(void *dev_handle, uint8_t scl, uint8_t sda)
|
||||
case I2C_TRANSMIT_START:
|
||||
if (!dev->scl && scl)
|
||||
dev->state = I2C_TRANSMIT;
|
||||
if (dev->scl && scl && !dev->last_sda && sda) { /* stop bit */
|
||||
i2c_gpio_log(2, "I2C GPIO %s: Stop bit received (from TRANSMIT_START)\n", dev->bus_name);
|
||||
if (dev->scl && scl && !dev->last_sda && sda) { /* stop condition */
|
||||
i2c_gpio_log(2, "I2C GPIO %s: Stop condition received (from TRANSMIT_START)\n", dev->bus_name);
|
||||
dev->state = I2C_IDLE;
|
||||
i2c_gpio_stop(dev);
|
||||
}
|
||||
@@ -327,7 +331,7 @@ i2c_gpio_get_sda(void *dev_handle)
|
||||
return dev->sda;
|
||||
|
||||
case I2C_RECEIVE_WAIT:
|
||||
return 0; /* ack */
|
||||
return dev->receive_wait_sda;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
|
||||
@@ -186,47 +186,6 @@ write_fifo(serial_t *dev, uint8_t dat)
|
||||
}
|
||||
|
||||
|
||||
#include <windows.h>
|
||||
#include <86box/pit.h>
|
||||
HANDLE serialdbg = NULL;
|
||||
OVERLAPPED serialdbgoverlapped_r;
|
||||
OVERLAPPED serialdbgoverlapped_w;
|
||||
uint8_t serialdbg_reading = 0;
|
||||
DWORD serialdbg_read;
|
||||
uint8_t serialdbg_buf[1];
|
||||
pc_timer_t serialdbgtimer;
|
||||
void
|
||||
serial_dbg_timer(void *p)
|
||||
{
|
||||
double dbps = (double) 115200;
|
||||
double temp = 0.0;
|
||||
int word_len = 32;
|
||||
temp = (double) word_len;
|
||||
temp = (1000000.0 / dbps) * temp;
|
||||
if (serialdbg_reading) {
|
||||
if (HasOverlappedIoCompleted(&serialdbgoverlapped_r)) {
|
||||
if (!GetOverlappedResult(serialdbg, &serialdbgoverlapped_r, &serialdbg_read, FALSE)) {
|
||||
return;
|
||||
}
|
||||
//pclog("overlapped %d\n", serialdbg_read);
|
||||
for (uint32_t i = 0; i < serialdbg_read; i++) {
|
||||
pclog("reading %02X\n", serialdbg_buf[i]);
|
||||
serial_write_fifo((serial_t *) p, serialdbg_buf[i]);
|
||||
}
|
||||
serialdbg_reading = 0;
|
||||
}// else pclog(" not yet\n");
|
||||
} else {
|
||||
if (!ReadFile(serialdbg, serialdbg_buf, sizeof(serialdbg_buf), &serialdbg_read, &serialdbgoverlapped_r) && GetLastError() != ERROR_IO_PENDING) {
|
||||
pclog("serial broken (read) %08X\n", GetLastError());
|
||||
CancelIo(serialdbg);
|
||||
return;
|
||||
}
|
||||
serialdbg_reading = 1;
|
||||
}
|
||||
timer_on_auto(&serialdbgtimer, temp);//((serial_t *) p)->transmit_period);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
serial_write_fifo(serial_t *dev, uint8_t dat)
|
||||
{
|
||||
@@ -234,8 +193,6 @@ serial_write_fifo(serial_t *dev, uint8_t dat)
|
||||
|
||||
if (!(dev->mctrl & 0x10))
|
||||
write_fifo(dev, dat);
|
||||
else
|
||||
pclog("fifo not in rx mode?\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -246,14 +203,6 @@ serial_transmit(serial_t *dev, uint8_t val)
|
||||
write_fifo(dev, val);
|
||||
else if (dev->sd->dev_write)
|
||||
dev->sd->dev_write(dev, dev->sd->priv, val);
|
||||
if (serialdbg && dev->base_address == SERIAL1_ADDR) {
|
||||
uint8_t buf[1];
|
||||
buf[0] = val;
|
||||
pclog("writing %02X...", buf[0]);
|
||||
WriteFile(serialdbg, buf, 1, NULL, &serialdbgoverlapped_w);
|
||||
//while (!HasOverlappedIoCompleted(&serialdbgoverlapped_w));
|
||||
pclog("written\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -374,7 +323,6 @@ serial_update_speed(serial_t *dev)
|
||||
|
||||
if (timer_is_enabled(&dev->timeout_timer))
|
||||
timer_on_auto(&dev->timeout_timer, 4.0 * dev->bits * dev->transmit_period);
|
||||
//pclog("SPEED UPDATED!!! %f\n", dev->transmit_period);
|
||||
}
|
||||
|
||||
|
||||
@@ -756,15 +704,6 @@ serial_init(const device_t *info)
|
||||
|
||||
next_inst++;
|
||||
|
||||
if (dev->base_address == SERIAL1_ADDR) {
|
||||
serialdbg = CreateFileA(TEXT("\\\\.\\COM4"), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
|
||||
pclog("%02X\n", GetLastError());
|
||||
if (serialdbg)
|
||||
timer_add(&serialdbgtimer, serial_dbg_timer, dev, 1);
|
||||
else
|
||||
pclog("serial open failed??\n");
|
||||
}
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user