📄 mcdemo.c
字号:
*/
void checkMsg(void) {
ulong id;
unsigned char dlc;
unsigned char buf[8];
unsigned int flags;
canStatus stat;
int i;
stat = canRead(&id, buf, &dlc, &flags);
if (stat == canOK) {
// printf("Message rcvd: id=%d, dlc=%d, {%d,%d,%d,...}\r\n", (int)id, dlc, buf[0], buf[1], buf[2]);
for (i = 0; i < FOLDER_COUNT; i++)
if (checkFolderEnable(i) && folder_env[i] == id)
break;
if (i < FOLDER_COUNT) {
if (flags & canMSG_RTR) {
// An RTR message
switch(i) {
case doc_MayorsDocument:
mpPending = 0; // txMP(0);
break;
case doc_Inputs:
txInputs();
break;
}
} else {
// An ordinary message
switch(i) {
case doc_KingsDocument: // KP
if (dlc == 8)
rxKP(buf);
break;
case doc_ParamSetting: // Parameter setting
if (dlc == 8)
rxParam(buf);
break;
case doc_LEDcontrol: // LED control
if (dlc >= 1) {
LEDsave = (uchar)(buf[0] & 3);
setLEDs(LEDsave);
}
break;
case doc_RequestInputs: // Request Inputs
txInputs();
break;
}
if (mpPending != 255) {
txMP(mpPending);
mpPending = 255;
}
}
}
}
}
// Extracts an Envelop number from a message; it starts at buf[0].
// The highest bit decides if it is an extended CAN id or not and is kept,
// the other two reserved or control bits are cleared.
// We support extended CAN as we must be able to detect 0x1fffffff for an
// undefined base number.
ulong extractEnvelope(uchar *buf) {
return buf[0] + ((buf[1] + ((buf[2] +((buf[3] & 0x9f) << 8)) << 8)) << 8);
}
// Handle a King's Page. In buf, there is an 8 byte message.
void rxKP(uchar *buf) {
ulong env; // Has to be long, even if we support only standard CAN.
uchar i, folderNo, enableF, cmd;
if (buf[0] == 0 || buf[0] == nodeNo) {
switch(buf[1]) {
case 0: // KP0: Selects Action and Communication mode.
if (buf[2] && buf[2] < 4)
actMode = (actModesT)buf[2];
if (buf[3] && buf[3] < 4)
commMode = (commModesT)buf[3];
switch(actMode) {
case ckReset:
#ifdef __WIN32__
// doReset() won't return, so we must show the status now.
mcThread->showCKStatus();
#endif
doReset();
break;
case ckFreeze:
doFreeze();
break;
case ckRunning:
doRun();
break;
}
canSetCommMode(commMode);
#ifdef __WIN32__
mcThread->showCKStatus();
#endif
break;
case 1: // KP1: Provides the Base numbers, asks for a Mayor's response.
env = extractEnvelope(buf+4);
if ((env & 0x1fffffff) == 0x1fffffff)
baseNo = envInvalid;
else if (env != 0)
baseNo = env;
fixMPEnv();
if (buf[2] != 0xff) {
mpPending = buf[2]; // txMP(buf[2]);
}
#ifdef __WIN32__
mcThread->showCKStatus();
mcThread->showFolders();
#endif
break;
case 2: // Assigns an Envelope to a Folder
env = extractEnvelope(buf+2);
folderNo = buf[6];
enableF = (uchar)(buf[7] & 1);
cmd = (uchar)(buf[7] >> 1); // We demand the reserved bits to be zero.
// Find the folder with envelope env. Should there be more than one
// folder with this envelope, all will not be found.
for (i = 0; i < FOLDER_COUNT; i++)
if (folder_env[i] == env)
break;
switch(cmd) {
case 0: // Keep current assignment, ignore folderNo, only regard enableF.
if (i < FOLDER_COUNT)
setFolderEnable(i, enableF);
break;
case 1: // Assign the envelope env to the folder folderNo.
// We do not allow more than one envelope per folder.
if (folderNo < FOLDER_COUNT) {
folder_env[folderNo] = env;
setFolderEnable(folderNo, enableF);
}
break;
case 3: // Transfer the envelope env to to the folder folderNo.
// The old assignment is cancelled.
if (i < FOLDER_COUNT) {
folder_env[i] = envInvalid;
setFolderEnable(i, 0);
}
if (folderNo < FOLDER_COUNT) {
folder_env[folderNo] = env;
setFolderEnable(folderNo, enableF);
}
break;
case 2: // Expel this envelope from any assignment. Folder No is ignored.
if (!enableF) { // AAE has to be 100.
if (i < FOLDER_COUNT) {
setFolderEnable(i, 0);
folder_env[i] = envInvalid;
}
}
break;
default:
break;
}
#ifdef __WIN32__
mcThread->showFolders();
#endif
break;
case 9:
nodeNo = buf[3];
fixMPEnv();
if (buf[2] != 0xff) {
mpPending = buf[2]; // txMP(buf[2]);
}
#ifdef __WIN32__
mcThread->showCKStatus();
mcThread->showFolders();
#endif
case 16:
// As the connection between folder and document is fixed, we do
// not use these fields. We just make it possible to enable/disable
// a folder without having to specify the envelope number.
folderNo = buf[2];
if (buf[4]) {
enableF = (uchar)(buf[4] & 0x40);
if (folderNo < FOLDER_COUNT)
setFolderEnable(folderNo, enableF);
#ifdef __WIN32__
mcThread->showFolders();
#endif
}
break;
default:
break;
}
}
}
void txMP(uchar pageNo) {
uchar buf[8];
buf[0] = 0;
buf[1] = pageNo;
if (commMode != ckSilent && pageNo < 2 &&
folder_env[doc_MayorsDocument] != envInvalid) {
switch(pageNo) {
case 0:
strcpy((char*)buf+2, "!EAN!"); // Clears buf[7] as well.
break;
case 1:
strcpy((char*)buf+2, "SerNo"); // Clears buf[7] as well
break;
}
if (canWrite(folder_env[doc_MayorsDocument], buf, 8, 0) != canOK)
; // canWriteFailures++;
}
}
// Read the input variables (buttons, analogue value) and transmit a message.
// Inputs DLC = 2 RTR always enabled
// line 0: Bit 0..1 Current LED status
// Bit 2..4 Buttons 0..2, current value
// Bit 5..7 Buttons 0..2, sticky (cleared at Tx).
// line 1: Analog value, 0..255
void txInputs(void) {
uchar buf[2];
if (actMode == ckRunning && commMode == ckCommunicate &&
folder_env[doc_Inputs] != envInvalid && checkFolderEnable(doc_Inputs)) {
buf[0] = (uchar)((LEDsave & 3) | (getButtons() << 2) | (buttonsSticky << 5));
buf[1] = (uchar)getAnalogue();
if (canWrite(folder_env[doc_Inputs], buf, 2, 0) == canOK)
buttonsSticky = 0;
else
; // canWriteFailures++;
}
}
// Parse a paramter setting doucument.
// Parameter settings DLC = 8
// Page 0
// line 0: 0 (page number)
// line 1: Period to transmit the Inputs document, 1..255, 0 no transmissions
// line 2..7: 0
//
void rxParam(uchar *buf) {
unsigned int pSave = txPeriod;
txPeriod = buf[1] + (buf[2] << 8);
if (pSave == 0 && txPeriod != 0) // Make sure a message is transmitted at once.
txLastTime = timerValue()-txPeriod;
#ifdef __WIN32__
mcThread->showModuleStatus();
#endif
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -