Skip to content

Commit 3054e1f

Browse files
committed
Merge PR UnifiedEngineering#136: Advanced Command Interface + operational modes (AMBIENT, MAXTEMPOVERRIDE, SPLIT)
2 parents 892412d + dd67a2e commit 3054e1f

File tree

11 files changed

+341
-31
lines changed

11 files changed

+341
-31
lines changed

src/advancedcmd.c

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/*
2+
* advancedcmd.c - Advanced Command Interface for T-962 reflow controller
3+
*
4+
* Author: Ryan Densberger - radensb
5+
*
6+
* This program is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU General Public License for more details.
15+
16+
* You should have received a copy of the GNU General Public License
17+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
20+
#include <stdint.h>
21+
#include <stdio.h>
22+
#include "circbuffer.h"
23+
#include "serial.h"
24+
#include "advancedcmd.h"
25+
26+
//chkAdvCmd - See if an Advanced Command had been sent. If a valid command is buffered,
27+
//read the data into the struct and return 1.
28+
uint8_t chkAdvCmd(tcirc_buf* buf, advancedSerialCMD* cmd) {
29+
//check for a full header worth of bytes
30+
if (circ_buf_count(buf) < ADVCMD_OVERHEAD) return 0;
31+
//See if it is an advanced command
32+
if (circ_buf_peek(buf, ADVCMD_SYNC1_LOC) == 0xFF && circ_buf_peek(buf, ADVCMD_SYNC2_LOC) == 0x55) {
33+
//Check the header CRC
34+
if (calcCkSum(buf, ADVCMD_OVERHEAD - 1) != circ_buf_peek(buf, ADVCMD_OVERHEAD - 1)) {
35+
//header CRC failed, corrupt size byte -> flush and abort
36+
circ_buf_flush(buf);
37+
return 0;
38+
}
39+
//verify we have enough bytes buffered to verify a CRC -> if not, abort and try again next time
40+
if (circ_buf_count(buf) < ((unsigned)circ_buf_peek(buf, ADVCMD_SIZE_LOC) + ADVCMD_OVERHEAD)) return 0;
41+
42+
//there is a full, verifyable command in the ring - lets go!
43+
uart_readc(); uart_readc(); // flush the 0xFF55
44+
cmd->cmdSize = uart_readc();
45+
uart_readc(); // flush the valid header CRC
46+
//check the CRC for the data section
47+
if (calcCkSum(buf, cmd->cmdSize) != circ_buf_peek(buf, cmd->cmdSize)) {
48+
//CMD in ring failed CRC -> Flush and abort
49+
/*DEBUG*/
50+
//printf("Calculated CRC: %02X\n", calcCkSum(buf, cmd->cmdSize));
51+
//printf("Received CRC : %02X\n", circ_buf_peek(buf, cmd->cmdSize));
52+
//for (int i = 0; i < cmd->cmdSize + 1; ++i) {
53+
// if (i % 16 == 0) printf("\n");
54+
// printf("%02X, ", circ_buf_peek(buf, i));
55+
//}
56+
//printf("Corrupt. Flushing...\n");
57+
circ_buf_flush(buf); //corrupt
58+
return 0;
59+
} else {
60+
//CMD in ring passed CRC -> ACK, transfer data to cmd struct, flush, and report success
61+
printf("%c", ADVCMD_ACK);
62+
//get CMD
63+
cmd->cmd = uart_readc();
64+
//Get Data
65+
for (uint8_t i = 0; i < cmd->cmdSize; ++i) {
66+
cmd->data[i] = uart_readc();
67+
}
68+
circ_buf_flush(buf); //scrub clean
69+
return 1;
70+
}
71+
}
72+
return 0;
73+
}
74+
75+
//Fast and easy checksum
76+
uint8_t calcCkSum(tcirc_buf* buf, int length) {
77+
unsigned datSum = 0;
78+
for (uint8_t i = 0; i < length; ++i) {
79+
datSum += circ_buf_peek(buf, i);
80+
}
81+
return 0x100 - (datSum & 0xFF);
82+
}

src/advancedcmd.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#ifndef ADVANCEDCMD_H_
2+
#define ADVANCEDCMD_H_
3+
#include "circbuffer.h"
4+
5+
#define ADVCMD_SYNC1_LOC 0
6+
#define ADVCMD_SYNC2_LOC 1
7+
#define ADVCMD_SIZE_LOC 2
8+
#define ADVCMD_OVERHEAD 4
9+
#define ADVCMD_ACK 0x85
10+
11+
typedef enum eAdvancedCMDs {
12+
SetEEProfileCmd = 0xEE
13+
//add more advcmds here...
14+
} advcmd_t;
15+
16+
typedef struct {
17+
uint8_t cmdSize;
18+
uint8_t cmd;
19+
uint8_t data[256];
20+
} advancedSerialCMD;
21+
22+
typedef struct {
23+
uint8_t profileNum;
24+
uint16_t tempData[48];
25+
} EEProfileCMD;
26+
27+
uint8_t chkAdvCmd(tcirc_buf* buf, advancedSerialCMD* cmd);
28+
uint8_t calcCkSum(tcirc_buf* buf, int length);
29+
30+
#endif /*ADVANCEDCMD_H_*/

src/circbuffer.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,26 @@ int circ_buf_has_char(tcirc_buf *cbuf) {
5959
return (head != cbuf->tail);
6060
}
6161

62+
void circ_buf_flush(tcirc_buf * cbuf) {
63+
cbuf->tail = cbuf->head;
64+
}
65+
66+
char circ_buf_peek(tcirc_buf * cbuf, int offset) {
67+
unsigned peekTail = cbuf->tail + offset;
68+
if (peekTail >= CIRCBUFSIZE) {
69+
peekTail -= CIRCBUFSIZE;
70+
}
71+
return cbuf->buf[peekTail];
72+
}
73+
74+
char* circ_buf_getAddr(tcirc_buf * cbuf, int offset) {
75+
unsigned addrTail = cbuf->tail + offset;
76+
if (addrTail >= CIRCBUFSIZE) {
77+
addrTail -= CIRCBUFSIZE;
78+
}
79+
return &cbuf->buf[addrTail];
80+
}
81+
6282
unsigned int circ_buf_count(tcirc_buf *cbuf) {
6383
int count;
6484

src/circbuffer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ typedef struct {
2020
void init_circ_buf(tcirc_buf * cbuf);
2121
void add_to_circ_buf(tcirc_buf *cbuf, char ch, int block);
2222
int circ_buf_has_char(tcirc_buf *cbuf);
23+
void circ_buf_flush(tcirc_buf *cbuf);
24+
char circ_buf_peek(tcirc_buf * cbuf, int offset);
25+
char* circ_buf_getAddr(tcirc_buf * cbuf, int offset);
2326
char get_from_circ_buf(tcirc_buf *cbuf);
2427
unsigned int circ_buf_count(tcirc_buf *cbuf);
2528

src/main.c

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <stdio.h>
2424
#include <string.h>
2525
#include "serial.h"
26+
#include "advancedcmd.h"
2627
#include "lcd.h"
2728
#include "io.h"
2829
#include "sched.h"
@@ -69,6 +70,10 @@ static char* help_text = \
6970
" about Show about + debug information\n" \
7071
" bake <setpoint> Enter Bake mode with setpoint\n" \
7172
" bake <setpoint> <time> Enter Bake mode with setpoint for <time> seconds\n" \
73+
" set OpMode <mode> Set Operational Mode (0-AMBIENT, 1-MAXTEMPOVERRIDE, 2-SPLIT)\n" \
74+
" set OpThresh <thresh> Set MAXTEMPOVERRIDE or SPLIT mode threshold in C (0-255)\n" \
75+
" get OpMode Get Operational Mode\n" \
76+
" get OpThresh Get MAXTEMPOVERRIDE or SPLIT mode threshold in C\n" \
7277
" help Display help text\n" \
7378
" list profiles List available reflow profiles\n" \
7479
" list settings List machine settings\n" \
@@ -135,6 +140,8 @@ int main(void) {
135140
SPI_TC_Init();
136141
Reflow_Init();
137142
SystemFan_Init();
143+
printf("\nCurrent Operational Mode: "); Sensor_printOpMode(); printf("\n");
144+
printf("Current Operational Mode Threshold: %u C\n", Sensor_getOpModeThreshold());
138145

139146
Sched_SetWorkfunc(MAIN_WORK, Main_Work);
140147
Sched_SetState(MAIN_WORK, 1, TICKS_SECS(3)); // Enable in 3 seconds
@@ -197,8 +204,44 @@ static int32_t Main_Work(void) {
197204
char* cmd_bake = "bake %d %d";
198205
char* cmd_dump_profile = "dump profile %d";
199206
char* cmd_setting = "setting %d %f";
200-
201-
if (uart_isrxready()) {
207+
char* cmd_setOpMode = "set OpMode %d";
208+
char* cmd_setOpModeThresh = "set OpThresh %d";
209+
210+
advancedSerialCMD advCmd = { 0 };
211+
212+
if (uart_chkAdvCmd(&advCmd)) {
213+
switch (advCmd.cmd) {
214+
case SetEEProfileCmd:
215+
{
216+
EEProfileCMD EEcmd;
217+
memcpy(&EEcmd, &advCmd.data, sizeof(advCmd.data));
218+
219+
if (EEcmd.profileNum == 1 || EEcmd.profileNum == 2) {
220+
printf("\nSetting EE profile %d:\n ", advCmd.data[0]);
221+
Reflow_SelectEEProfileIdx(EEcmd.profileNum);
222+
for (unsigned char i = 0; i < NUMPROFILETEMPS; ++i) {
223+
Reflow_SetSetpointAtIdx(i, EEcmd.tempData[i]);
224+
}
225+
Reflow_SaveEEProfile();
226+
if (EEcmd.profileNum == 1) Reflow_DumpProfile(5); //CUSTOM#1
227+
else Reflow_DumpProfile(6); //CUSTOM#2
228+
}
229+
else {
230+
printf("\nOnly EEPROM profile 1 and 2 are supported for this command.\n");
231+
}
232+
//reset advCmd
233+
//memset(&advCmd, 0, sizeof(advCmd));
234+
break;
235+
}
236+
//Add more advanced commands here
237+
//case ...
238+
default: {
239+
printf("\nUnknown Advanced Command entered.\n");
240+
//memset(&advCmd, 0, sizeof(advCmd));
241+
uart_rxflush();
242+
}
243+
}
244+
} else if (uart_available() > 3) {
202245
int len = uart_readline(serial_cmd, 255);
203246

204247
if (len > 0) {
@@ -252,6 +295,31 @@ static int32_t Main_Work(void) {
252295
Sensor_ListAll();
253296
printf("\n");
254297

298+
} else if (strcmp(serial_cmd, "get OpMode") == 0) {
299+
printf("\nCurrent Operational Mode: "); Sensor_printOpMode(); printf("\n");
300+
301+
} else if (strcmp(serial_cmd, "get OpThresh") == 0) {
302+
printf("\nCurrent Operational Mode Threshold: %u C\n", Sensor_getOpModeThreshold());
303+
304+
} else if (sscanf(serial_cmd, cmd_setOpMode, &param) > 0) {
305+
// set operational mode
306+
if (param > 2 || param < 0) {
307+
printf("\nOnly options are 0-2. See Help.\n");
308+
309+
} else {
310+
Sensor_setOpMode((OperationMode_t)param);
311+
printf("\nOperational Mode Set: "); Sensor_printOpMode(); printf("\n");
312+
}
313+
314+
} else if (sscanf(serial_cmd, cmd_setOpModeThresh, &param) > 0) {
315+
// set operational mode threshold
316+
if (param > 255 || param < 0) {
317+
printf("\nOnly options are 0-255\n");
318+
} else {
319+
Sensor_setOpModeThreshold((uint8_t)param);
320+
printf("\nOperational Mode Threshold Set: %d C\n", param);
321+
}
322+
255323
} else if (sscanf(serial_cmd, cmd_select_profile, &param) > 0) {
256324
// select profile
257325
Reflow_SelectProfileIdx(param);

src/nvstorage.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ typedef enum eNVItem {
1919

2020
SCREENSAVER_ACTIVE,
2121

22+
OP_MODE,
23+
MODE_THRESH,
2224

2325
NVITEM_NUM_ITEMS // Last value
2426
} NVItem_t;

0 commit comments

Comments
 (0)