Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
179 changes: 145 additions & 34 deletions lib/bus/comlynx/comlynx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
#include "led.h"
#include <cstring>

#define IDLE_TIME 1000 // Idle tolerance in microseconds
#define IDLE_TIME 500 // Idle tolerance in microseconds (roughly three characters at 62500 baud)

//systemBus SYSTEM_BUS.;

static QueueHandle_t reset_evt_queue = NULL;

Expand Down Expand Up @@ -78,18 +80,58 @@ uint8_t comlynx_checksum(uint8_t *buf, unsigned short len)

void virtualDevice::comlynx_send(uint8_t b)
{
Debug_printf("comlynx_send_buffer: %X\n", b);

// Wait for idle only when in UDPStream mode
if (SYSTEM_BUS._udpDev->udpstreamActive)
SYSTEM_BUS.wait_for_idle();

// Write the byte
ComLynx.wait_for_idle();
fnUartBUS.write(b);
fnUartBUS.flush();
fnUartBUS.read();
}

void virtualDevice::comlynx_send_buffer(uint8_t *buf, unsigned short len)
{
ComLynx.wait_for_idle();
fnUartBUS.write(buf,len);
fnUartBUS.readBytes(buf,len);

//buf[len] = '\0';
//Debug_printf("comlynx_send_buffer: %d %s\n", len, buf); // causes out of bounds write in disk routines

//Debug_printf("comlynx_send_buffer: len:%d %0X %0X %0X %0X %0X %0X\n", len, buf[0], buf[1], buf[2], buf[3], buf[4], buf[len-1]);
Debug_printf("comlynx_send_buffer: len:%d\n", len);

// Wait for idle only when in UDPStream mode
if (SYSTEM_BUS._udpDev->udpstreamActive)
SYSTEM_BUS.wait_for_idle();

fnUartBUS.write(buf, len);
fnUartBUS.readBytes(buf, len);
}

bool virtualDevice::comlynx_recv_ck()
{
uint8_t recv_ck, ck;


while (fnUartBUS.available() <= 0)
fnSystem.yield();

// get checksum
recv_ck = fnUartBUS.read();

ck = comlynx_checksum(recvbuffer, recvbuffer_len);

// debugging checksum values
//Debug_printf("comlynx_recv_ck, recv:%02X calc:%02X\n", recv_ck, ck);

// reset receive buffer
recvbuffer_len = 0;

if (recv_ck == ck)
return true;
else
return false;
}

uint8_t virtualDevice::comlynx_recv()
Expand All @@ -101,6 +143,11 @@ uint8_t virtualDevice::comlynx_recv()

b = fnUartBUS.read();

// Add to receive buffer
recvbuffer[recvbuffer_len] = b;
recvbuffer_len++;

//Debug_printf("comlynx_recv: %x\n", b);
return b;
}

Expand Down Expand Up @@ -136,19 +183,32 @@ uint16_t virtualDevice::comlynx_recv_length()
s = comlynx_recv() << 8;
s |= comlynx_recv();

if (s > 1024)
s = 1024;

// Reset recv buffer, but maybe we want checksum over the length too? -SJ
recvbuffer_len = 0;

return s;
}

void virtualDevice::comlynx_send_length(uint16_t l)
{
ComLynx.wait_for_idle();
comlynx_send(l >> 8);
comlynx_send(l & 0xFF);
}

unsigned short virtualDevice::comlynx_recv_buffer(uint8_t *buf, unsigned short len)
{
return fnUartBUS.readBytes(buf, len);
unsigned short b;

b = fnUartBUS.readBytes(buf, len);

// Add to receive buffer
memcpy(&recvbuffer[recvbuffer_len], buf, len);
recvbuffer_len += len;

return(b);
}

uint32_t virtualDevice::comlynx_recv_blockno()
Expand Down Expand Up @@ -180,35 +240,32 @@ void virtualDevice::comlynx_control_ready()
comlynx_response_ack();
}

void systemBus::wait_for_idle()
bool systemBus::wait_for_idle()
{
bool isIdle = false;
int64_t start, current, dur;
int trashCount = 0;

do
{
// Wait for serial line to quiet down.
while (fnUartBUS.available() > 0)
{
fnUartBUS.read();
trashCount++;
}
// SJ notes: we really don't need to do this unless we are in UDPStream mode
// Likely we want to just wait until the bus is "idle" for about 3 character times
// which is about 0.5 ms at 62500 baud 8N1
//
// Check that the bus is truly idle for the whole duration, and then we can start sending?

if (trashCount > 0)
Debug_printf("wait_for_idle() dropped %d bytes\n", trashCount);
start = esp_timer_get_time();

start = current = esp_timer_get_time();
do {
current = esp_timer_get_time();
dur = current - start;

while ((fnUartBUS.available() <= 0) && (isIdle == false))
{
current = esp_timer_get_time();
dur = current - start;
if (dur > IDLE_TIME)
isIdle = true;
}
} while (isIdle == false);
fnSystem.yield();
// Did we get any data in the FIFO while waiting?
if (fnUartBUS.available() > 0)
return false;

} while (dur < IDLE_TIME);

// Must have been idle at least IDLE_TIME to get here
return true;

//fnSystem.yield(); // not sure if we need to do this, from old function - SJ
}

void virtualDevice::comlynx_process(uint8_t b)
Expand All @@ -218,7 +275,7 @@ void virtualDevice::comlynx_process(uint8_t b)

void virtualDevice::comlynx_control_status()
{
ComLynx.start_time = esp_timer_get_time();
//SYSTEM_BUS.start_time = esp_timer_get_time();
comlynx_response_status();
}

Expand Down Expand Up @@ -262,10 +319,19 @@ void systemBus::_comlynx_process_cmd()
uint8_t b;

b = fnUartBUS.read();
start_time = esp_timer_get_time();
//start_time = esp_timer_get_time();

uint8_t d = b & 0x0F;

#ifdef DEBUG
if ((b & 0xF0) == (MN_ACK<<4))
Debug_println("Lynx sent ACK");
else {
Debug_println("---");
Debug_printf("comlynx_process_cmd: dev:%X cmd:%X\n", d, (b & 0xF0)>>4);
}
#endif

// Find device ID and pass control to it
if (_daisyChain.count(d) < 1)
{
Expand Down Expand Up @@ -453,9 +519,54 @@ void systemBus::setUDPHost(const char *hostname, int port)
}

// Restart UDP Stream mode if needed
if (_udpDev->udpstreamActive)
if (_udpDev->udpstreamActive) {
_udpDev->comlynx_disable_udpstream();
if (_udpDev->udpstream_host_ip != IPADDR_NONE)
_udpDev->comlynx_disable_redeye();
}
if (_udpDev->udpstream_host_ip != IPADDR_NONE) {
_udpDev->comlynx_enable_udpstream();
if (_udpDev->redeye_mode)
_udpDev->comlynx_enable_redeye();
}
}


void systemBus::setRedeyeMode(bool enable)
{
Debug_printf("setRedeyeMode, %d\n", enable);
_udpDev->redeye_mode = enable;
_udpDev->redeye_logon = true;
}


void systemBus::setRedeyeGameRemap(uint32_t remap)
{
Debug_printf("setRedeyeGameRemap, %d\n", remap);

// handle pure updstream games
if ((remap >> 8) == 0xE1) {
_udpDev->redeye_mode = false; // turn off redeye
_udpDev->redeye_logon = true; // reset logon phase toggle
_udpDev->redeye_game = remap; // set game, since we can't detect it
}

// handle redeye game that need remapping
if (remap != 0xFFFF) {
_udpDev->remap_game_id = true;
_udpDev->new_game_id = remap;
}
else {
_udpDev->remap_game_id = false;
_udpDev->new_game_id = 0xFFFF;
}
}


/*void systemBus::setComlynxIdleTime(uint64_t idle_time)
{
Debug_printf("setComlynxIdleTime, %d\n", idle_time);

SYSTEM_BUS.comlynx_idle_time = idle_time;
}*/

#endif /* BUILD_LYNX */
25 changes: 22 additions & 3 deletions lib/bus/comlynx/comlynx.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,12 @@ class virtualDevice
*/
void comlynx_send_buffer(uint8_t *buf, unsigned short len);

/**
* @brief Receive checksum byte and compare with checksum calculation
* @return true or false
*/
bool comlynx_recv_ck();

/**
* @brief Receive byte from Comlynx
* @return byte received
Expand Down Expand Up @@ -204,6 +210,12 @@ class virtualDevice
*/
uint16_t response_len;

/**
* Receive buffer and length
*/
uint8_t recvbuffer[1024];
uint16_t recvbuffer_len = 0;

public:

/**
Expand Down Expand Up @@ -235,26 +247,29 @@ class systemBus
virtualDevice *_activeDev = nullptr;
lynxFuji *_fujiDev = nullptr;
lynxPrinter *_printerDev = nullptr;
lynxUDPStream *_udpDev = nullptr;


void _comlynx_process_cmd();
void _comlynx_process_queue();

public:
lynxUDPStream *_udpDev = nullptr;

void setup();
void service();
void shutdown();
void reset();

/**
* @brief Wait for Comlynx bus to become idle.
* @brief Wait to see if Comlynx bus is idle.
*/
void wait_for_idle();
bool wait_for_idle();

/**
* stopwatch
*/
int64_t start_time;
//int64_t comlynx_idle_time = 1000;

int numDevices();
void addDevice(virtualDevice *pDevice, uint8_t device_id);
Expand All @@ -269,10 +284,14 @@ class systemBus
QueueHandle_t qComlynxMessages = nullptr;
void setUDPHost(const char *newhost, int port); // Set new host/ip & port for UDP Stream

void setRedeyeMode(bool enable);
void setRedeyeGameRemap(uint32_t remap);

bool shuttingDown = false; // TRUE if we are in shutdown process
bool getShuttingDown() { return shuttingDown; };
};

extern systemBus SYSTEM_BUS;
//extern systemBus ComLynx;

#endif /* COMLYNX_H */
Loading
Loading