Are the equivalent of interrupts in involved?
Do i have to defend against recursion?
I am looking at the XC manual, and see the following regarding select case:
"Case statements are not permitted to contain output operations as the XMOS archi- tecture requires an output operation to complete but allows an input operation to wait until it sees a matching output before committing to its completion."
followed by the following code:
select {
....
case isTX => tmrTX when timerafter(txTime) :> void :
if (txI < 8)
TX <: >> txByte;
......
}
Which looks a lot like an output operation.
I am including my code for comment on correct usage. With the pollTimer commented out, it works properly. When un-commented, it stumbles and pauses.
Code: Select all
typedef enum {
IDLE,
CHECK_ADDR,
GET_SEQ,
GET_CMD,
GET_CHANNEL,
GET_DATA_SIZE,
GET_CRC,
GET_DATA,
GET_DATA_CRC
} COMMS_STATE_t;
typedef enum {
GET_SEQss,
GET_CMDss,
GET_CHANNELss,
GET_DATA_SIZEss,
GET_DATAss
} COMMS_STATESS_t;
typedef enum {
SET_DAC = 0,
GET_ADC = 1,
SET_IO_BYTE = 2,
GET_IO_BYTE = 3,
SET_XRAY_ON = 4,
SET_XRAY_OFF = 5,
GET_XRAY_STATUS = 6,
SET_RTC_BYTE = 7,
GET_RTC_BYTE = 8,
INIT_FLASH = 9,
PAGE_FLASH = 10,
FINISH_FLASH = 11,
SET_POLLING =12,
SET_POLL_INTERVAL =13,
GET_GPIO = 0x00ab
} CMD_t;
void analogInterface(chanend rx, chanend tx, chanend status, chanend legacyRx, chanend legacyTx)
{
COMMS_STATESS_t ss = GET_SEQss;
unsigned cmd;
int seq;
int channel;
unsigned dataSize;
unsigned char cData[2*8]; // for now the only thing passed is a single 4 byte int, later, <8> 2 byte ints
int charsRemaining;
unsigned data;
timer pollTimer;
timer legacyTimer;
unsigned int legacyTime;
unsigned int pollTime;
static int xraysON = 0;
int val;
unsigned tripVal;
unsigned gpioVal = 0;
unsigned seqss = 0;
int getKV = 0;
unsigned kv = 128;
unsigned ma = 64;
unsigned legacyVal;
unsigned dacValue = 0;
unsigned char pollTable = 0;
unsigned pollInterval = 500;
p_spi1_select <: 11;
spi1_init(1,100,20,0,0,0,0); // ADC max clck = 2.5Mhz
// expanderInit(xraysON);
pollTimer :> pollTime;
legacyTimer :> legacyTime;
p_trip :> tripVal;
status <: (tripVal & 0x0001);
tx <: (int) 0;
tx <: (unsigned) 0x00aa;
tx <: (unsigned) 0;
tx <: (unsigned) 4;
uintToChar(cData,tripVal,4);
for (int i=0;i<4;i++)
tx <: (unsigned)cData[i];
while (1)
{
select
{
case p_trip when pinsneq(tripVal) :> tripVal:
status <: ((tripVal & 0x0001) | (gpioVal & 0x0002));
tx <: seqss++;
tx <: (unsigned) 0x00aa;
tx <: (unsigned) 0;
tx <: (unsigned) 4;
uintToChar(cData,tripVal,4);
for (int i=0;i<4;i++)
tx <: (unsigned)cData[i];
break;
case rx :> val:
if (val == -1) {ss = GET_SEQss;}
else {
switch (ss){
case GET_SEQss:
seq = val;
ss++;
break;
case GET_CMDss:
cmd = val;
ss++;
break;
case GET_CHANNELss:
channel = val;
ss++;
break;
case GET_DATA_SIZEss:
dataSize = val;
charsRemaining = dataSize;
if (dataSize >0)
{
ss++;
}
else
{
ss = GET_SEQss;
commandHandler (gpioVal, xraysON,pollTable, pollInterval, cmd,channel, cData,dataSize);
status <: ((tripVal & 0x0001) | (gpioVal & 0x0002));
tx <: seq;
tx <: (unsigned) cmd;
tx <: channel;
tx <: dataSize;
for (int i=0;i<dataSize;i++)
tx <: (unsigned)cData[i];
}
break;
case GET_DATAss:
cData[dataSize - charsRemaining] = (unsigned char) val;
charsRemaining--;
if (charsRemaining <= 0)
{
ss = GET_SEQss;
commandHandler (gpioVal, xraysON,pollTable, pollInterval, cmd,channel, cData,dataSize);
status <: ((tripVal & 0x0001) | (gpioVal & 0x0002));
tx <: seq;
tx <: (unsigned) cmd;
tx <: channel;
tx <: dataSize;
for (int i=0;i<dataSize;i++)
tx <: (unsigned)cData[i];
}
break;
default:
break;
}
}
break;
case legacyTimer when timerafter(legacyTime) :> void:
legacyTime += LEGACY_POLL_INTERVAL;
if (dacValue < 4000)
dacWrite(xraysON,(dacValue % 4),dacValue);
dacValue++;
if (dacValue > 6000)
dacValue = 0;
getKV = !getKV;
if (getKV)
{
kv = adcRead(xraysON,KV_CHANNEL) >> 4;
legacyTx <: kv;
}
else
{
ma = adcRead(xraysON,MA_CHANNEL) >> 4;
ma |= 0x100;
legacyTx <: ma;
}
break;
/* case pollTimer when timerafter(pollTime) :> void:
pollTime += pollInterval * TICKS_PER_us;
tx <: seqss++;
tx <: (unsigned) 0x00aa;
tx <: (unsigned) 0;
tx <: (unsigned) 4;
uintToChar(cData,tripVal,4);
for (int i=0;i<4;i++)
tx <: (unsigned)cData[i];
break;
*/ }
}
}
I am also including a second code snippet, which I think might be a more correct usage, where I post outputs to a queue, and execute using the default: statements Any comments greatly appreciated.
Code: Select all
void handleComms(chanend pg_ch, chanend rx_ch,chanend tx_ch,chanend analogRX_ch,chanend analogTX_ch, chanend flashRX_ch, chanend flashTX_ch )
{
COMMS_STATESS_t ss = GET_SEQss;
COMMS_STATESS_t ssA = GET_SEQss;
char msg[] = "\n\rNEXT GEN XRAY CONTROLLER R16b\n\r";
unsigned rxChar;
int charsRemaining = 0;
char rxString[8];
COMMS_STATE_t cState;
unsigned boardAddr = 0;
int val;
int useCRC=1;
int LEDon = 0;
timer t;
unsigned int time;
unsigned gpioVal;
unsigned gpioValOld=0;
unsigned ledSeq = 0;
unsigned head = 0;
unsigned tail = 0;
unsigned addr;
unsigned cmd[MAX_DEPTH];
unsigned seq[MAX_DEPTH];
unsigned channel[MAX_DEPTH];
unsigned dataSize[MAX_DEPTH];
unsigned crcRxVal;
unsigned char cData[MAX_DEPTH][MAX_DATA_WORDS];
unsigned crcDataRxVal;
unsigned cmdssA;
unsigned seqssA;
unsigned channelssA;
unsigned dataSizessA;
int charsRemainingssA;
unsigned char cDatassA[16];
unsigned cmdss;
unsigned seqss;
unsigned channelss;
unsigned dataSizess;
int charsRemainingss;
unsigned char cDatass[16];
unsigned char buffer[BUFF_LEN];
unsigned bufferHeadPtr = 0;
unsigned bufferTailPtr = 0;
unsigned pg5Vval;
unsigned crcCalcVal;
char crcString[MAX_DATA_WORDS*2];
unsigned crcPtr = 0;
char debugmsg[8];
int charsRead;
commsIO <: 6;
for (int i=0; i<sizeof(msg); i++) {
buffer[bufferHeadPtr++] = msg[i];
}
t :> time;
time+=500000;
crcInit();
while (1)
{
select
{
case rx_ch :> rxChar:
if (!( (cState == GET_CRC) || (cState == IDLE) || (cState == GET_DATA_CRC))) crcString[crcPtr++] = rxChar;
if (rxChar == PREAMBLE_CHAR) {cState = IDLE;}
if (rxChar == PREAMBLE_CHAR_NO_CRC) {cState = IDLE;}
switch (cState)
{
case IDLE:
if (rxChar == PREAMBLE_CHAR) {charsRemaining = 2; cState++; useCRC=1; crcPtr = 0; if (DEBUG > 1) {tx_ch <: (unsigned)PREAMBLE_CHAR;}}
if (rxChar == PREAMBLE_CHAR_NO_CRC) {charsRemaining = 2; cState++; useCRC=0; crcPtr = 0; if (DEBUG > 1) {tx_ch <: (unsigned)PREAMBLE_CHAR_NO_CRC;}}
break;
case CHECK_ADDR:
charsRemaining--;
rxString[charsRemaining] = rxChar;
if (charsRemaining <= 0) {
charsRemaining = 2;
addr = getHexUnsigned(rxString,2);
if (addr == boardAddr) {if (DEBUG > 1) {tx_ch <: (unsigned)'a';} cState++;}
else {if (DEBUG > 1) {tx_ch <: (unsigned)'x';} cState = IDLE;}
}
break;
case GET_SEQ:
charsRemaining--;
rxString[charsRemaining] = rxChar;
if (charsRemaining <= 0) {
charsRemaining = 2;
seq[head] = getHexUnsigned(rxString,2);
if (DEBUG > 1) {tx_ch <: (unsigned)'s';}
cState++;
}
break;
case GET_CMD:
charsRemaining--;
rxString[charsRemaining] = rxChar;
if (charsRemaining <= 0) {
charsRemaining = 2;
cmd[head] = getHexUnsigned(rxString,2);
if (DEBUG > 1) {tx_ch <: (unsigned)'c';}
cState++;
}
break;
case GET_CHANNEL:
charsRemaining--;
rxString[charsRemaining] = rxChar;
if (charsRemaining <= 0) {
charsRemaining = 4;
channel[head] = getHexUnsigned(rxString,2);
if (DEBUG > 1) {tx_ch <: (unsigned)'h';}
cState++;
}
break;
case GET_DATA_SIZE:
charsRemaining--;
rxString[charsRemaining] = rxChar;
if (charsRemaining <= 0) {
if (DEBUG > 1) {tx_ch <: (unsigned)'s';}
charsRemaining = 8;
dataSize[head] = getHexUnsigned(rxString,4);
cState++;
}
break;
case GET_CRC:
charsRemaining--;
rxString[charsRemaining] = rxChar;
if (charsRemaining <= 0) {
if (DEBUG > 1) {tx_ch <: (unsigned)'r';}
crcCalcVal = fullCRC(crcString,crcPtr) & 0xffffffff;
crcRxVal = getHexUnsigned(rxString,8);
if (crcRxVal == crcCalcVal){
if (DEBUG > 1) {tx_ch <: (unsigned)'y';}
if (dataSize[head]){
charsRemaining = 2 * dataSize[head];
crcPtr = 0;
cState++;
}
else{
head++;
if (head >= MAX_DEPTH) { head = 0; }
cState = IDLE;
}
}
else {
if (DEBUG > 1) {tx_ch <: (unsigned)'n';}
cState = IDLE;
}
}
break;
case GET_DATA:
charsRemaining--;
rxString[charsRemaining % 2] = rxChar;
if ((charsRemaining % 2) == 0){
cData[head][(dataSize[head] - 1) - charsRemaining/2] = getHexUnsigned(rxString,2);
}
if (charsRemaining <= 0) {
if (DEBUG > 1) {tx_ch <: (unsigned)'d';}
charsRemaining = 8;
cState++;
}
break;
case GET_DATA_CRC:
charsRemaining--;
rxString[charsRemaining] = rxChar;
if (charsRemaining <= 0) {
if (DEBUG > 1) {tx_ch <: (unsigned)'r';}
cState = IDLE;
crcCalcVal = fullCRC(crcString,crcPtr) & 0xffffffff;
if (DEBUG>1){
tx_ch <: (unsigned)'[';
while (crcPtr >0)
{
crcPtr--;
tx_ch <: (unsigned)crcString[crcPtr];
}
tx_ch <: (unsigned)']';
}
crcRxVal = getHexUnsigned(rxString,8);
if (crcRxVal == crcCalcVal){
if (DEBUG > 1) {tx_ch <: (unsigned)'y';}
head++;
if (head >= MAX_DEPTH) { head = 0; }
}
else
{
if (DEBUG > 1) {tx_ch <: (unsigned)'n';}
}
}
break;
}
break;
case flashTX_ch :> val:
switch (ssA){
case GET_SEQss:
seqssA = val;
ssA++;
break;
case GET_CMDss:
cmdssA = val;
ssA++;
break;
case GET_CHANNELss:
channelssA = val;
ssA++;
break;
case GET_DATA_SIZEss:
dataSizessA = val;
charsRemainingssA = val;
if (dataSizessA >0)
{
ssA++;
}
else
{
ssA = GET_SEQss;
bufferHeadPtr = responseString(buffer, bufferHeadPtr, bufferTailPtr, boardAddr, seqssA, cmdssA, channelssA, dataSizessA, cDatassA);
}
break;
case GET_DATAss:
cDatassA[dataSizessA - charsRemainingssA] = (unsigned char)val;
charsRemainingssA--;
if (charsRemainingssA <= 0)
{
bufferHeadPtr = responseString(buffer, bufferHeadPtr, bufferTailPtr, boardAddr, seqssA, cmdssA, channelssA, dataSizessA, cDatassA);
ssA = GET_SEQss;
}
break;
}
break;
case analogTX_ch :> val:
if (val == -1) {ss = GET_SEQss;}
else {
switch (ss){
case GET_SEQss:
seqss = val;
ss++;
break;
case GET_CMDss:
cmdss = val;
ss++;
break;
case GET_CHANNELss:
channelss = val;
ss++;
break;
case GET_DATA_SIZEss:
dataSizess = val;
charsRemainingss = val;
if (dataSizess >0)
{
ss++;
}
else
{
bufferHeadPtr = responseString(buffer, bufferHeadPtr, bufferTailPtr, boardAddr, seqss, cmdss, channelss, dataSizess, cDatass);
ss = GET_SEQss;
}
break;
case GET_DATAss:
cDatass[dataSizess - charsRemainingss] = (unsigned char)val;
charsRemainingss--;
if (charsRemainingss <= 0)
{
bufferHeadPtr = responseString(buffer, bufferHeadPtr, bufferTailPtr, boardAddr, seqss, cmdss, channelss, dataSizess, cDatass);
ss = GET_SEQss;
}
break;
}
}
break;
case pg_ch :> pg5Vval:
buffer[0] = 'V'; // we want immediate send
bufferHeadPtr = 1;
bufferTailPtr = 0;
break;
case t when timerafter(time) :> void:
ledSeq++;
if ((ledSeq % 100) == 0)
{
ledSeq = 0;
LEDon = !LEDon;
if (LEDon) {commsIO <: 14;}
else {commsIO <: 6;}
}
time+=500000;
gpio :> gpioVal;
gpioVal &= GP_IN_PORT_MASK;
if (gpioVal != gpioValOld) {
gpioValOld = gpioVal;
cmd[head] = GET_GPIO;
seq[head] = 0;
channel[head] = 0;
dataSize[head] = 4;
uintToChar(cData[head],gpioVal,4);
head++;
if (head >= MAX_DEPTH) { head = 0; }
}
break;
default:
if (head != tail)
{
switch (cmd[tail]) {
case SET_RTC_BYTE:
flashRX_ch <: seq[tail];
flashRX_ch <: cmd[tail];
flashRX_ch <: channel[tail];
flashRX_ch <: dataSize[tail];
for (int i =0; i<dataSize[tail];i++){
flashRX_ch <: (unsigned) cData[tail][i];
}
break;
case GET_RTC_BYTE:
flashRX_ch <: seq[tail];
flashRX_ch <: cmd[tail];
flashRX_ch <: channel[tail];
flashRX_ch <: dataSize[tail];
for (int i =0; i<dataSize[tail];i++){
flashRX_ch <: (unsigned) cData[tail][i];
}
break;
case INIT_FLASH:
flashRX_ch <: seq[tail];
flashRX_ch <: cmd[tail];
flashRX_ch <: channel[tail];
flashRX_ch <: dataSize[tail];
for (int i =0; i<dataSize[tail];i++){
flashRX_ch <: (unsigned) cData[tail][i];
}
break;
case PAGE_FLASH:
flashRX_ch <: seq[tail];
flashRX_ch <: cmd[tail];
flashRX_ch <: channel[tail];
flashRX_ch <: dataSize[tail];
for (int i =0; i<dataSize[tail];i++){
flashRX_ch <: (unsigned) cData[tail][i];
}
break;
case FINISH_FLASH:
flashRX_ch <: seq[tail];
flashRX_ch <: cmd[tail];
flashRX_ch <: channel[tail];
flashRX_ch <: dataSize[tail];
for (int i =0; i<dataSize[tail];i++){
flashRX_ch <: (unsigned) cData[tail][i];
}
break;
default:
analogRX_ch <: seq[tail];
analogRX_ch <: cmd[tail];
analogRX_ch <: channel[tail];
analogRX_ch <: dataSize[tail];
for (int i =0; i<dataSize[tail];i++){
analogRX_ch <: (unsigned) cData[tail][i];
}
break;
}
tail++;
if (tail >= MAX_DEPTH) {tail = 0;}
}
if (bufferHeadPtr != bufferTailPtr)
{
tx_ch <: (unsigned) buffer[(bufferTailPtr++)%BUFF_LEN];
if (bufferTailPtr >= BUFF_LEN) {bufferTailPtr = 0;}
}
break;
}
}
}