Need advice on VIA control (PORT A)
Posted: Sun Nov 15, 2020 9:58 am
DBug suggested that I come here for some advice on the VIA.
The Oric connects to the 8bit-Hub through the printer port. The trick consists of switching PORT A to input/output mode when receiving/sending data. The code does this 20 times per second, which gives a theoretical bandwidth of 5 KB/s (20*256 bytes).
The system works correctly, and it is possible to pass UDP/TCP packets to 8bit-OS and 8bit-Slicks. But after a few minutes (I would 5-10), the VIA stops toggling PORT A (the humming sound stops). A soft reset (through the CUMANA Reborn) fixes the issue, and gives another few minutes of PORT A communication. So it looks like a software issue is at play (rather than hardware).
I wonder if there is need for some register to be reset? I am pasting the CC65 Hub communication code here, hoping for some insights from veteran members... The main points of interest are the UpdateHub(), SendByte() and ReceiveByte().
The Oric connects to the 8bit-Hub through the printer port. The trick consists of switching PORT A to input/output mode when receiving/sending data. The code does this 20 times per second, which gives a theoretical bandwidth of 5 KB/s (20*256 bytes).
The system works correctly, and it is possible to pass UDP/TCP packets to 8bit-OS and 8bit-Slicks. But after a few minutes (I would 5-10), the VIA stops toggling PORT A (the humming sound stops). A soft reset (through the CUMANA Reborn) fixes the issue, and gives another few minutes of PORT A communication. So it looks like a software issue is at play (rather than hardware).
I wonder if there is need for some register to be reset? I am pasting the CC65 Hub communication code here, hoping for some insights from veteran members... The main points of interest are the UpdateHub(), SendByte() and ReceiveByte().
Code: Select all
unsigned char tick;
unsigned char hubState[7] = { COM_ERR_OFFLINE, 255, 255, 255, 255, 80, 100 };
unsigned char sendID = 0, sendLen = 0, sendHub[256];
unsigned char recvID = 0, recvLen = 0, recvHub[256];
unsigned char packetID = 0;
unsigned char QueueHub(unsigned char packetCmd, unsigned char* packetBuffer, unsigned char packetLen)
{
unsigned char i;
// Check if there is enough space in buffer
if (packetLen > 255-sendLen)
return 0;
// Add to send buffer
if (++packetID > 15) { packetID = 1; }
sendHub[sendLen++] = packetID;
sendHub[sendLen++] = packetLen+1;
sendHub[sendLen++] = packetCmd;
for (i=0; i<packetLen; i++)
sendHub[sendLen++] = packetBuffer[i];
return 1;
}
void SendByte(unsigned char value)
{
// Send 1 byte to HUB
POKE(0x0301, value); // Write to Printer Port
POKE(0x0300, 175); // Send STROBE (falling signal)
tick++; tick++; tick++; // Wait 3 cycles
POKE(0x0300, 255); // Reset STROBE
}
unsigned char RecvByte(unsigned char* value)
{
// Recv 1 byte from HUB
unsigned char i = 255;
while (1) { // Countdown i to 0
if (PEEK(0x030d)&2) { *value = PEEK(0x0301); break; } // Look for ACKNOW on CA1 then read Printer Port
if (!i--) return 0;
}
return 1;
}
void RecvHub()
{
unsigned char i, len, ID, packetLen;
unsigned char header, footer, checksum;
SendByte(85); // Ask Hub to send us some Data
POKE(0x0303, 0); // Set Port A as Input
i = PEEK(0x0301); // Reset ORA
// Check header
if (!RecvByte(&header) || header != 170) {
if (hubState[0] != COM_ERR_OFFLINE) { hubState[0] = COM_ERR_HEADER; }
return;
}
// Get packet ID
if (!RecvByte(&ID)) { hubState[0] = COM_ERR_TRUNCAT; return; }
// Read joystick/mouse data
for (i=1; i<7; i++) {
if (!RecvByte(&hubState[i])) { hubState[0] = COM_ERR_TRUNCAT; return; }
}
// Get buffer length
if (!RecvByte(&len)) { hubState[0] = COM_ERR_TRUNCAT; return; }
// Read buffer data
for (i=0; i<len; i++) {
if (!RecvByte(&recvHub[i])) { hubState[0] = COM_ERR_TRUNCAT; return; }
}
// Get footer
if (!RecvByte(&footer)) { hubState[0] = COM_ERR_TRUNCAT; return; }
// Verify checkum
checksum = ID;
for (i=1; i<7; i++) { checksum += hubState[i]; }
for (i=0; i<len; i++) { checksum += recvHub[i]; }
if (footer != checksum) {
hubState[0] = COM_ERR_CORRUPT;
return;
}
hubState[0] = COM_ERR_OK;
// Check packet reception
if (ID != recvID) {
// Check ID against last packet sent
if ((ID & 0x0f) == sendID) {
// Shift any remaining data
packetLen = sendHub[1]+2;
if (packetLen < sendLen) {
memcpy(&sendHub[0], &sendHub[packetLen], sendLen-packetLen);
sendLen -= packetLen;
} else {
sendLen = 0;
}
}
// Check ID against last packet received
if (len && ((ID & 0xf0) != (recvID & 0xf0)))
recvLen = len;
// Update ID
recvID = ID;
}
}
void SendHub()
{
unsigned char i, checksum, packetLen;
// Send Header
SendByte(170);
// Send Packet ID
if (sendLen) { sendID = sendHub[0]; }
checksum = (recvID & 0xf0) + sendID;
SendByte(checksum);
// Send Packet Data (if any)
if (sendLen) {
packetLen = sendHub[1];
SendByte(packetLen);
for (i=2; i<packetLen+2; i++) {
SendByte(sendHub[i]);
checksum += sendHub[i];
}
} else {
SendByte(0);
}
// Send footer
SendByte(checksum);
}
clock_t updateClock;
void UpdateHub()
{
unsigned char i;
// Throttle requests to respect refresh rate
if (clock() < updateClock)
return;
updateClock = clock()+HUB_REFRESH_RATE;
// Was hub already initialized?
if (hubState[0] == COM_ERR_OFFLINE) {
// Queue reset command
if (sendHub[0] != HUB_SYS_RESET) {
recvID = 0; recvLen = 0;
sendID = 0; sendLen = 0;
QueueHub(HUB_SYS_RESET, 0, 0);
}
}
__asm__("sei"); // Disable interrupts
// Process HUB I/O
SendHub();
RecvHub();
POKE(0x0303, 255); // Set port A as Output
__asm__("cli"); // Resume interrupts
}