-
Notifications
You must be signed in to change notification settings - Fork 10
/
xsvfduino.ino
131 lines (118 loc) · 2.72 KB
/
xsvfduino.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
///
// An XSVF player for the Arduino
//
// Tested with the STM32 Arduino clone known as the Blue Pill
//
// Settings:
// Board: BluePill F103CB
// USB: Virtual COMM
// Serial: SerialUSB
#if MENU_SERIAL != SerialUSB
#error "Make sure that the SerialUSB option is selected"
#endif
#define LED PC13
uint8_t xsvf_buf[32]; // 32-bit chunks
int8_t xsvf_buf_ptr = 32, xsvf_buf_len = 0;
#include "ports.h"
#include "micro.h"
#include <stdio.h>
#include <stdarg.h>
#include <setjmp.h>
bool ongoing = false; // Is there an ongoing transmission?
jmp_buf glb_jmp_buf;
void debug_printf(char *format,...)
{
static bool send_g = true;
char buf[256];
va_list args;
va_start(args, format);
vsprintf(buf, format, args);
va_end(args);
if (send_g)
{
Serial.print('G'); // TODO: send this only at the beginning of a line
send_g = false;
}
if ( strchr(buf, '\n') != NULL )
send_g = true;
Serial.print(buf);
Serial.flush();
yield();
if ( !strncmp(buf, "ERROR", 5) )
longjmp(glb_jmp_buf, 1);
}
uint8_t read_data()
{
if (xsvf_buf_ptr < xsvf_buf_len)
return xsvf_buf[xsvf_buf_ptr++];
if (ongoing)
Serial.println("A"); // Todo: send extra info with the ack (debug info?)
xsvf_buf_len = -1;
xsvf_buf_ptr = 0;
while(xsvf_buf_len < 32)
{
uint32_t t0 = millis(), t1 = t0;
while(!Serial.available())
{
uint32_t t2 = millis();
if (t2 - t1 > 500)
{
digitalWrite(LED, !digitalRead(LED)); // Toggles the LED
t1 = t2;
}
if (t2 - t0 > 1000) // Timeout waiting for packet
{
if (xsvf_buf_ptr < xsvf_buf_len) // Any data on the buffer?
{
return xsvf_buf[xsvf_buf_ptr++]; // Yes, return it
}
else
if (ongoing && t2 - t0 > 3000)
{
Serial.print("QINFO: Timeout waiting for a packet. (End of Data?)\n");
Serial.flush();
yield();
longjmp(glb_jmp_buf, 1); // Waiting for too long, reset the engine
}
}
yield();
}
uint8_t c = Serial.read();
ongoing = true;
if (xsvf_buf_len < 0)
{
if (c == 'D') // Data packet TODO: packet numbering and CRC checking
xsvf_buf_len = 0; // Receive the rest of the packet
if (c == 'R')
Serial.println("A");
}
else
{
if (xsvf_buf_len < 32)
{
xsvf_buf[xsvf_buf_len++] = c;
}
}
}
return xsvf_buf[xsvf_buf_ptr++];
}
void u_sleep( uint32_t m )
{
delayMicroseconds( m );
}
void setup()
{
initPorts();
pinMode(LED, OUTPUT);
digitalWrite(LED, HIGH);
Serial.begin(115200);
Serial.println("A");
}
int cnt = 1;
String buf;
void loop()
{
ongoing = false;
if ( !setjmp(glb_jmp_buf) )
xsvfExecute();
}