-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmenu.c
212 lines (184 loc) · 6.63 KB
/
menu.c
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
#include "menu.h"
#include "main.h"
#include "led.h"
#include <stdio.h>
#include <inttypes.h>
// extern GLOBALS
// local global data structures
char receive_buffer[32];
unsigned char receive_buffer_position;
char send_buffer[32];
// A generic function for whenever you want to print to your serial comm window.
// Provide a string and the length of that string. My serial comm likes "\r\n" at
// the end of each string (be sure to include in length) for proper linefeed.
void print_usb( char *buffer, int n ) {
serial_send( USB_COMM, buffer, n );
wait_for_sending_to_finish();
}
//------------------------------------------------------------------------------------------
// Initialize serial communication through USB and print menu options
// This immediately readies the board for serial comm
void init_menu() {
char printBuffer[32];
// Set the baud rate to 9600 bits per second. Each byte takes ten bit
// times, so you can get at most 960 bytes per second at this speed.
serial_set_baud_rate(USB_COMM, 9600);
// Start receiving bytes in the ring buffer.
serial_receive_ring(USB_COMM, receive_buffer, sizeof(receive_buffer));
//memcpy_P( send_buffer, PSTR("USB Serial Initialized\r\n"), 24 );
//snprintf( printBuffer, 24, "USB Serial Initialized\r\n");
//print_usb( printBuffer, 24 );
print_usb( "USB Serial Initialized\r\n", 24);
//memcpy_P( send_buffer, MENU, MENU_LENGTH );
print_usb( MENU, MENU_LENGTH );
}
//------------------------------------------------------------------------------------------
// process_received_byte: Parses a menu command (series of keystrokes) that
// has been received on USB_COMM and processes it accordingly.
// The menu command is buffered in check_for_new_bytes_received (which calls this function).
void process_received_string(const char* buffer)
{
// Used to pass to USB_COMM for serial communication
int length;
char tempBuffer[32];
// parse and echo back to serial comm window (and optionally the LCD)
char color;
char op_char;
int value;
int parsed;
parsed = sscanf(buffer, "%c %c %d", &op_char, &color, &value);
#ifdef ECHO2LCD
lcd_goto_xy(0,0);
printf("Got %c %c %d\n", op_char, color, value);
#endif
length = sprintf( tempBuffer, "Op:%c C:%c V:%d\r\n", op_char, color, value );
print_usb( tempBuffer, length );
// convert color to upper and check if valid
color -= 32*(color>='a' && color<='z');
switch (color) {
case 'R':
case 'G':
case 'Y':
case 'A': break;
default:
print_usb( "Bad Color. Try {RGYA}\r\n", 23 );
print_usb( MENU, MENU_LENGTH);
return;
}
// Check valid command and implement
switch (op_char) {
// change toggle period <color> LED
case 'T':
case 't':
// setPeriod( color, value );
break;
// print counter for <color> LED
case 'P':
case 'p':
switch(color) {
case 'R':
length = sprintf( tempBuffer, "R toggles: %d\r\n", G_redToggles );
print_usb( tempBuffer, length );
break;
case 'G':
break;
case 'Y':
break;
case 'A':
break;
default:
print_usb("Default in p(color). How did I get here?\r\n", 42 );
}
break;
// zero counter for <color> LED
case 'Z':
case 'z':
switch(color) {
case 'R':
break;
case 'G':
break;
case 'Y':
break;
case 'A':
break;
default:
print_usb("Default in z(color). How did I get here?\r\n", 42 );
}
break;
default:
print_usb( "Command does not compute.\r\n", 27 );
} // end switch(op_char)
print_usb( MENU, MENU_LENGTH);
} //end menu()
//---------------------------------------------------------------------------------------
// If there are received bytes to process, this function loops through the receive_buffer
// accumulating new bytes (keystrokes) in another buffer for processing.
void check_for_new_bytes_received()
{
/*
The receive_buffer is a ring buffer. The call to serial_check() (you should call prior to this function) fills the buffer.
serial_get_received_bytes is an array index that marks where in the buffer the most current received character resides.
receive_buffer_position is an array index that marks where in the buffer the most current PROCESSED character resides.
Both of these are incremented % (size-of-buffer) to move through the buffer, and once the end is reached, to start back at the beginning.
This process and data structures are from the Pololu library. See examples/serial2/test.c and src/OrangutanSerial/*.*
A carriage return from your comm window initiates the transfer of your keystrokes.
All key strokes prior to the carriage return will be processed with a single call to this function (with multiple passes through this loop).
On the next function call, the carriage return is processes with a single pass through the loop.
The menuBuffer is used to hold all keystrokes prior to the carriage return. The "received" variable, which indexes menuBuffer, is reset to 0
after each carriage return.
*/
char menuBuffer[32];
static int received = 0;
// while there are unprocessed keystrokes in the receive_buffer, grab them and buffer
// them into the menuBuffer
while(serial_get_received_bytes(USB_COMM) != receive_buffer_position)
{
// place in a buffer for processing
menuBuffer[received] = receive_buffer[receive_buffer_position];
++received;
// Increment receive_buffer_position, but wrap around when it gets to
// the end of the buffer.
if ( receive_buffer_position == sizeof(receive_buffer) - 1 )
{
receive_buffer_position = 0;
}
else
{
receive_buffer_position++;
}
}
// If there were keystrokes processed, check if a menue command
if (received) {
// if only 1 received, it was MOST LIKELY a carriage return.
// Even if it was a single keystroke, it is not a menu command, so ignore it.
if ( 1 == received ) {
received = 0;
return;
}
// Process buffer: terminate string, process, reset index to beginning of array to receive another command
menuBuffer[received] = '\0';
#ifdef ECHO2LCD
lcd_goto_xy(0,1);
print("RX: (");
print_long(received);
print_character(')');
for (int i=0; i<received; i++)
{
print_character(menuBuffer[i]);
}
#endif
process_received_string(menuBuffer);
received = 0;
}
}
//-------------------------------------------------------------------------------------------
// wait_for_sending_to_finish: Waits for the bytes in the send buffer to
// finish transmitting on USB_COMM. We must call this before modifying
// send_buffer or trying to send more bytes, because otherwise we could
// corrupt an existing transmission.
void wait_for_sending_to_finish()
{
while(!serial_send_buffer_empty(USB_COMM))
serial_check(); // USB_COMM port is always in SERIAL_CHECK mode
}