Skip to content

Commit 672c0a0

Browse files
Lynx code WIP merge (#1032)
* Lynx WIP code * Added checksum checking to Fujinet commands * Further cleanup and small fixes * Added checksum to fuji, disk and network. General cleanup * lynx disk changes - partial blocks accounted for - checksum, ack/nack receive in disk block send media type changes - basically removed media type detection, treat all files the same misc cleanup * Use MEDIA_BLOCK_SIZE in all disk routines, general cleanup * Fixed bug in blocksize calculation General cleanup, fixes * mostly debugging message cleanup (lynx serial packets start with ---) some fixes in json parse function, took code from sio implementation * Fixes differences from upstream * fixed out of bounds write to array in comlynx_send_buffer debugging statement
1 parent fa95544 commit 672c0a0

File tree

17 files changed

+960
-306
lines changed

17 files changed

+960
-306
lines changed

lib/bus/comlynx/comlynx.cpp

Lines changed: 145 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
#include "led.h"
1414
#include <cstring>
1515

16-
#define IDLE_TIME 1000 // Idle tolerance in microseconds
16+
#define IDLE_TIME 500 // Idle tolerance in microseconds (roughly three characters at 62500 baud)
17+
18+
//systemBus SYSTEM_BUS.;
1719

1820
static QueueHandle_t reset_evt_queue = NULL;
1921

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

7981
void virtualDevice::comlynx_send(uint8_t b)
8082
{
83+
Debug_printf("comlynx_send_buffer: %X\n", b);
84+
85+
// Wait for idle only when in UDPStream mode
86+
if (SYSTEM_BUS._udpDev->udpstreamActive)
87+
SYSTEM_BUS.wait_for_idle();
88+
8189
// Write the byte
82-
ComLynx.wait_for_idle();
8390
fnUartBUS.write(b);
8491
fnUartBUS.flush();
8592
fnUartBUS.read();
8693
}
8794

8895
void virtualDevice::comlynx_send_buffer(uint8_t *buf, unsigned short len)
8996
{
90-
ComLynx.wait_for_idle();
91-
fnUartBUS.write(buf,len);
92-
fnUartBUS.readBytes(buf,len);
97+
98+
//buf[len] = '\0';
99+
//Debug_printf("comlynx_send_buffer: %d %s\n", len, buf); // causes out of bounds write in disk routines
100+
101+
//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]);
102+
Debug_printf("comlynx_send_buffer: len:%d\n", len);
103+
104+
// Wait for idle only when in UDPStream mode
105+
if (SYSTEM_BUS._udpDev->udpstreamActive)
106+
SYSTEM_BUS.wait_for_idle();
107+
108+
fnUartBUS.write(buf, len);
109+
fnUartBUS.readBytes(buf, len);
110+
}
111+
112+
bool virtualDevice::comlynx_recv_ck()
113+
{
114+
uint8_t recv_ck, ck;
115+
116+
117+
while (fnUartBUS.available() <= 0)
118+
fnSystem.yield();
119+
120+
// get checksum
121+
recv_ck = fnUartBUS.read();
122+
123+
ck = comlynx_checksum(recvbuffer, recvbuffer_len);
124+
125+
// debugging checksum values
126+
//Debug_printf("comlynx_recv_ck, recv:%02X calc:%02X\n", recv_ck, ck);
127+
128+
// reset receive buffer
129+
recvbuffer_len = 0;
130+
131+
if (recv_ck == ck)
132+
return true;
133+
else
134+
return false;
93135
}
94136

95137
uint8_t virtualDevice::comlynx_recv()
@@ -101,6 +143,11 @@ uint8_t virtualDevice::comlynx_recv()
101143

102144
b = fnUartBUS.read();
103145

146+
// Add to receive buffer
147+
recvbuffer[recvbuffer_len] = b;
148+
recvbuffer_len++;
149+
150+
//Debug_printf("comlynx_recv: %x\n", b);
104151
return b;
105152
}
106153

@@ -136,19 +183,32 @@ uint16_t virtualDevice::comlynx_recv_length()
136183
s = comlynx_recv() << 8;
137184
s |= comlynx_recv();
138185

186+
if (s > 1024)
187+
s = 1024;
188+
189+
// Reset recv buffer, but maybe we want checksum over the length too? -SJ
190+
recvbuffer_len = 0;
191+
139192
return s;
140193
}
141194

142195
void virtualDevice::comlynx_send_length(uint16_t l)
143196
{
144-
ComLynx.wait_for_idle();
145197
comlynx_send(l >> 8);
146198
comlynx_send(l & 0xFF);
147199
}
148200

149201
unsigned short virtualDevice::comlynx_recv_buffer(uint8_t *buf, unsigned short len)
150202
{
151-
return fnUartBUS.readBytes(buf, len);
203+
unsigned short b;
204+
205+
b = fnUartBUS.readBytes(buf, len);
206+
207+
// Add to receive buffer
208+
memcpy(&recvbuffer[recvbuffer_len], buf, len);
209+
recvbuffer_len += len;
210+
211+
return(b);
152212
}
153213

154214
uint32_t virtualDevice::comlynx_recv_blockno()
@@ -180,35 +240,32 @@ void virtualDevice::comlynx_control_ready()
180240
comlynx_response_ack();
181241
}
182242

183-
void systemBus::wait_for_idle()
243+
bool systemBus::wait_for_idle()
184244
{
185-
bool isIdle = false;
186245
int64_t start, current, dur;
187-
int trashCount = 0;
188246

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

198-
if (trashCount > 0)
199-
Debug_printf("wait_for_idle() dropped %d bytes\n", trashCount);
253+
start = esp_timer_get_time();
200254

201-
start = current = esp_timer_get_time();
255+
do {
256+
current = esp_timer_get_time();
257+
dur = current - start;
202258

203-
while ((fnUartBUS.available() <= 0) && (isIdle == false))
204-
{
205-
current = esp_timer_get_time();
206-
dur = current - start;
207-
if (dur > IDLE_TIME)
208-
isIdle = true;
209-
}
210-
} while (isIdle == false);
211-
fnSystem.yield();
259+
// Did we get any data in the FIFO while waiting?
260+
if (fnUartBUS.available() > 0)
261+
return false;
262+
263+
} while (dur < IDLE_TIME);
264+
265+
// Must have been idle at least IDLE_TIME to get here
266+
return true;
267+
268+
//fnSystem.yield(); // not sure if we need to do this, from old function - SJ
212269
}
213270

214271
void virtualDevice::comlynx_process(uint8_t b)
@@ -218,7 +275,7 @@ void virtualDevice::comlynx_process(uint8_t b)
218275

219276
void virtualDevice::comlynx_control_status()
220277
{
221-
ComLynx.start_time = esp_timer_get_time();
278+
//SYSTEM_BUS.start_time = esp_timer_get_time();
222279
comlynx_response_status();
223280
}
224281

@@ -262,10 +319,19 @@ void systemBus::_comlynx_process_cmd()
262319
uint8_t b;
263320

264321
b = fnUartBUS.read();
265-
start_time = esp_timer_get_time();
322+
//start_time = esp_timer_get_time();
266323

267324
uint8_t d = b & 0x0F;
268325

326+
#ifdef DEBUG
327+
if ((b & 0xF0) == (MN_ACK<<4))
328+
Debug_println("Lynx sent ACK");
329+
else {
330+
Debug_println("---");
331+
Debug_printf("comlynx_process_cmd: dev:%X cmd:%X\n", d, (b & 0xF0)>>4);
332+
}
333+
#endif
334+
269335
// Find device ID and pass control to it
270336
if (_daisyChain.count(d) < 1)
271337
{
@@ -453,9 +519,54 @@ void systemBus::setUDPHost(const char *hostname, int port)
453519
}
454520

455521
// Restart UDP Stream mode if needed
456-
if (_udpDev->udpstreamActive)
522+
if (_udpDev->udpstreamActive) {
457523
_udpDev->comlynx_disable_udpstream();
458-
if (_udpDev->udpstream_host_ip != IPADDR_NONE)
524+
_udpDev->comlynx_disable_redeye();
525+
}
526+
if (_udpDev->udpstream_host_ip != IPADDR_NONE) {
459527
_udpDev->comlynx_enable_udpstream();
528+
if (_udpDev->redeye_mode)
529+
_udpDev->comlynx_enable_redeye();
530+
}
531+
}
532+
533+
534+
void systemBus::setRedeyeMode(bool enable)
535+
{
536+
Debug_printf("setRedeyeMode, %d\n", enable);
537+
_udpDev->redeye_mode = enable;
538+
_udpDev->redeye_logon = true;
460539
}
540+
541+
542+
void systemBus::setRedeyeGameRemap(uint32_t remap)
543+
{
544+
Debug_printf("setRedeyeGameRemap, %d\n", remap);
545+
546+
// handle pure updstream games
547+
if ((remap >> 8) == 0xE1) {
548+
_udpDev->redeye_mode = false; // turn off redeye
549+
_udpDev->redeye_logon = true; // reset logon phase toggle
550+
_udpDev->redeye_game = remap; // set game, since we can't detect it
551+
}
552+
553+
// handle redeye game that need remapping
554+
if (remap != 0xFFFF) {
555+
_udpDev->remap_game_id = true;
556+
_udpDev->new_game_id = remap;
557+
}
558+
else {
559+
_udpDev->remap_game_id = false;
560+
_udpDev->new_game_id = 0xFFFF;
561+
}
562+
}
563+
564+
565+
/*void systemBus::setComlynxIdleTime(uint64_t idle_time)
566+
{
567+
Debug_printf("setComlynxIdleTime, %d\n", idle_time);
568+
569+
SYSTEM_BUS.comlynx_idle_time = idle_time;
570+
}*/
571+
461572
#endif /* BUILD_LYNX */

lib/bus/comlynx/comlynx.h

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,12 @@ class virtualDevice
9292
*/
9393
void comlynx_send_buffer(uint8_t *buf, unsigned short len);
9494

95+
/**
96+
* @brief Receive checksum byte and compare with checksum calculation
97+
* @return true or false
98+
*/
99+
bool comlynx_recv_ck();
100+
95101
/**
96102
* @brief Receive byte from Comlynx
97103
* @return byte received
@@ -204,6 +210,12 @@ class virtualDevice
204210
*/
205211
uint16_t response_len;
206212

213+
/**
214+
* Receive buffer and length
215+
*/
216+
uint8_t recvbuffer[1024];
217+
uint16_t recvbuffer_len = 0;
218+
207219
public:
208220

209221
/**
@@ -235,26 +247,29 @@ class systemBus
235247
virtualDevice *_activeDev = nullptr;
236248
lynxFuji *_fujiDev = nullptr;
237249
lynxPrinter *_printerDev = nullptr;
238-
lynxUDPStream *_udpDev = nullptr;
250+
239251

240252
void _comlynx_process_cmd();
241253
void _comlynx_process_queue();
242254

243255
public:
256+
lynxUDPStream *_udpDev = nullptr;
257+
244258
void setup();
245259
void service();
246260
void shutdown();
247261
void reset();
248262

249263
/**
250-
* @brief Wait for Comlynx bus to become idle.
264+
* @brief Wait to see if Comlynx bus is idle.
251265
*/
252-
void wait_for_idle();
266+
bool wait_for_idle();
253267

254268
/**
255269
* stopwatch
256270
*/
257271
int64_t start_time;
272+
//int64_t comlynx_idle_time = 1000;
258273

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

287+
void setRedeyeMode(bool enable);
288+
void setRedeyeGameRemap(uint32_t remap);
289+
272290
bool shuttingDown = false; // TRUE if we are in shutdown process
273291
bool getShuttingDown() { return shuttingDown; };
274292
};
275293

276294
extern systemBus SYSTEM_BUS;
295+
//extern systemBus ComLynx;
277296

278297
#endif /* COMLYNX_H */

0 commit comments

Comments
 (0)