Sending commands to PIC - c

First my PIC is 16f1625 and I use MPLAB 8.86 for programming it.
My problem is simple, I have communicating between PC and PIC,PC sends one byte and PIC reads this byte, and do something.
My problem is that I would like to improve this for like this, PC send one letter like "R" and after he send the number that I'd like to set. Today i only have 4 possibility, PC send 0,1,2 or 5 and I set the resolution according to these.
switch(i) {
case 1:
pulsesPerMm = 10;
break;
case 2:
pulsesPerMm = 20;
break;
case 5:
pulsesPerMm = 51;
break;
case 10:
pulsesPerMm = 102;
break;
}
I receive the command like these:
while(!RCIF) /* set when register is not empty */
continue;
return RCREG;
Now I want to do something like this: I receive "R" that indicates that the next word will be resolution and after these, 2 bytes, that will be the new resolution and i will only have to do is convert the string into int (using atoi) and then i can set the pulsesPerMm.
The problem is that I have other commands that only requires one letter, so I don't want to change these.

Switch on rx chars instead of numbers then, in your 'R' case block only, call the getChar() function to return the next two chars and atoi() them.

Related

Small regex nfa matching while possibly larger matches are running

I'm creating my own lexical analyzer generator, similar to (f)lex. My plan was to make a tool like grep and go from there. Right now I've followed the articles by Russ Cox on creating an analyzer as a virtual machine: https://swtch.com/~rsc/regexp/regexp2.html
The issue I've run into is keeping track of small matches while a larger match is running. An example where this could happen is ".*d|ab" on the input string "abcabcabcabcabcabcd".
Currently, I have an NFA running which is practically the same as the one Cox made. It uses thompsons algorithm to compute dfa sets on the fly from the nfa. The threads are stored in a sparse set. (Preston Briggs and Linda Torczon's 1993 paper, “An Efficient Representation for Sparse Sets,”)
Threads that appear earlier in this list have larger importance and eliminate later threads upon accepting.
My current implementation can find a word matching a regex, but cannot continously keep on matching. To show what currently happens, lets look at the above example regex and string.
The first step makes three threads. Two for the left side of the union, one for the right side. Only the threads taking the wildcard and 'a' advance into the next list.
Step two advances again the wildcard and the thread taking a 'b' this time. It also adds new thread to try and match from this character as starting point.
Step three advances the wildcard and puts the thread running "ab" into an accepting state. Now the newer (less priority) threads are removed and a new threads are added to start matching from this character.
This is where the problem starts: The nfa cannot output a match on "ab" yet. It should wait for ".*d" to finish. This means that for a large input file, a lot of matches should be buffered until the ".*d" terminates (which is at the last character to get the potential largest match)
Thus, the actual question is: What is an efficient way to store these matches or is there another way to not have to potentially buffer the whole input file?
As a side note on the code: The code is so similar to the article of Cox that any questions related to how the code functions can be viewed in the article. Also, I've downloaded and tested the code of Cox and it had the same issue as described above.
What I hope to get with the solution to this question is to get my nfa implementation to match text in the exact same way grep or lex would: with the longest leftmost matches.
As requested, code fragments:
VM opcodes representing ".*d|ab":
0 SPLIT 2, 5
1 ANY
2 SPLIT 1, 3
3 CHAR 'd'
4 JMP 7
5 CHAR 'a'
6 CHAR 'b'
7 ACCEPT
CHAR asserts input character to match first operand.
SPLIT creates two new threads starting at the first and second operand.
ANY matches any input character.
JMP sets the program counter to the first operand.
ACCEPT puts the current thread in an accepting state.
An add function to recursively go through opcodes until reaching an CHAR or ACCEPT opcode then adding these to the next threadlist.
static void recursive_add(struct NFA *nfa, struct Thread *thread)
{
switch(nfa->code[thread->pc])
{
case OPCODE_JMP:
printf(" | jmp\n");
thread->pc = nfa->code[thread->pc + 1];
recursive_add(nfa, thread);
break;
case OPCODE_SPLIT:
{
uint16_t pc = thread->pc;
printf(" | split: %d op1: %d op2: %d\n", thread->pc, nfa->code[thread->pc + 1], nfa->code[thread->pc + 2]);
thread->pc = nfa->code[thread->pc + 1];
recursive_add(nfa, thread);
thread->pc = nfa->code[pc + 2];
recursive_add(nfa, thread);
break;
}
case OPCODE_CHAR: case OPCODE_ACCEPT:
printf(" | char/accept %d\n", thread->pc);
add_sparseset(nfa->nthreads, thread);
return;
default:
fprintf(stderr, "Unexpected opcode %x at program counter %d\n", nfa->code[thread->pc], thread->pc);
exit(1);
}
}
And the main loop, currently a bit messy but this should give a better idea of what the code does.
void execute_nfa(struct NFA *nfa)
{
struct Thread thread;
struct SparseSet *swap;
char c;
for(;;)
{
c = getchar();
printf("Input char %c\n", c);
//add new starting thread for every character
thread.pc = 0;
recursive_add(nfa, &thread);
clear_sparseset(nfa->cthreads);
swap = nfa->cthreads;
nfa->cthreads = nfa->nthreads;
nfa->nthreads = swap;
for(unsigned int i = 0; i < nfa->cthreads->size; i++)
{
thread = *(((struct Thread *)nfa->cthreads->dense) + i);
printf(" thread pc: %d\n", thread.pc);
switch(nfa->code[thread.pc])
{
case OPCODE_CHAR:
if(nfa->code[thread.pc + 1] == c)
{
printf(" Add to next\n");
thread.pc += 2;
recursive_add(nfa, &thread);
}
break;
case OPCODE_ACCEPT:
printf(" accept (still need to do shit)\n");
break;
default:
fprintf(stderr, "Unexpected opcode %x at program counter %d\n", nfa->code[thread.pc], thread.pc);
exit(1);
}
}
}
}

Microcontroller receives the value "255ld" continuously via virtual serial port

I hope this is not a silly question, but I'm not able to find the answer to my problem myself.
I'm working on an Atmega32U4 microcontroller device, which is supposed to receive a series of bytes and store them. My code is based on a CDC Virtual Serial driver template from the LUFA-Library 151115. In order to test my code, I use the very useful tool ScriptCommunicator 04.11. The microcontroller unit (MCU) is connected via USB to the PC and is treated as a serial com port device by the PC host. My OS is Windows 7 64 bit.
Currently, I'm writing a function in which six values shall be received and stored.
For that I use the following code:
int16_t Register_1 = 0;
int16_t Register_2 = 0;
int16_t Register_3 = 0;
int16_t Register_4 = 0;
int16_t Register_5 = 0;
int16_t Register_6 = 0;
int16_t serial_byte = 0;
int8_t loop = 1;
do
{
serial_byte = CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface);
serial_byte &= 0x00FF;
switch (loop)
{
case 1: Register_1 = ad7194_byte; break;
case 2: Register_2 = ad7194_byte; break;
case 3: Register_3 = ad7194_byte; break;
case 4: Register_4 = ad7194_byte; break;
case 5: Register_5 = ad7194_byte; break;
case 6: Register_6 = ad7194_byte; break;
}
CDC_Device_USBTask(&VirtualSerial_CDC_Interface);
USB_USBTask();
loop ++ ;
printf("%i" PRId32 "\n", serial_byte) ;
_delay_ms(1000);
} while (loop < 7);
I have previously used a similar code snippet and everything seemed to be working fine. Now I identified the following problem:
The device is continuously reveiving the value "255ld". For when I test the above code with the ScriptCommunicator, I receive this value six times(which is why the printf-statement is included in the above code).
I have the suspicion that this happens because Windows is treating the MCU as a common USB device, e.g. a mouse? Could that be the case?
Or what could else be the reason for this?
How can I work around my problem?
Thanks in advance for any hints and answers!
Wrong use of format.
int16_t serial_byte = 0;
// v (remove i)
// printf("%i" PRId32 "\n", serial_byte) ;
// 16 not 32
printf("%" PRId16 "\n", serial_byte) ;
Thanks for the answer, which did not solve my problem directly, but kind of brought me to the solution.
Solution:
I received the 255 values although I didn't send anything to the MCU.
But:
If no byte is received, the LUFA CDC_Device_ReceiveByte-function returns -1. I forgot to check for that value before the serial_byte &= 0x00FF; statement. The -1 value was then mixed up and the 255 value turned out.
Silly mistake again, which costed me a lot of time again.

How to design a function which identifies when "+IPD," is arrived from UART?

I'm working with the Tiva Launchpad EK-TM4C123GXL and the ESP8266 WIFI module.
When this module gets a wifi packet, it sends it to the microcontroller through the UART port.
The format used by ESP8266 to send a packet (to the uC via UART) is:
+IPD,n:xxxxx\r\nOK\r\n
where:
n is the length (in bytes) of the data packet
: indicates that the next byte will be the first data byte
xxxxx is the data packet
\r\nOK\r\n are 6 bytes and they are useless for me.
For example:
+IPD,5:hello\r\nOK\r\n
Here is my situation:
I'm working on an existing project, where I can't change these two things:
1- The UART module is already configured to generate an interrupt when its Receive FIFO (of 16 bytes) is half-full.
2- The ISR (Interrupt Service Routine) which handles this interrupt:
reads only one byte from the UARTDR (UART Data Register)
saves it into a variable
calls a function (called rx_data()) which will handle that byte.
Now, I have to write this function, called rx_data(), in C language.
So, the message coming form the ESP8266 module is passed to this function, rx_data(), one byte at a time, and this function must be able to:
identify the header +IPD,
read the length n of the data packet
save the data packet xxxxx (which is located after the : character and before the first \r character) into a buffer
discard the final bytes \r\nOK\r\n (these 6 bytes are useless for me, but, anyway, I must read them to remove them from the Receive FIFO)
I think to work step by step, so now I' m reasoning on:
how to identify the +IPD, , considering that only one byte at a time is passed to this function?
It's time to make a state machine. Every time rx_data is called, you would update the state of your state machine, and eventually at some point you will know that you have received the string "+IPD,".
The simplest thing that could work would be something like this, assuming that the byte received from the UART is passed as an argument to rx_data:
void rx_data(uint8_t byte)
{
static uint8_t state = 0;
if (byte == '+') { state = 1; }
else if (state == 1 && byte == 'I') { state = 2; }
else if (state == 2 && byte == 'P') { state = 3; }
else if (state == 3 && byte == 'D') { state = 4; }
else if (state == 4 && byte == ',') {
state = 0;
handleIPDMessage(); // we received "+IPD,"
}
else { state = 0; }
}
You can see that handleIPDMessage() is called if and only if the last characters received were "+IPD,".
However, you should consider writing a more general state machine that would operate on lines instead of just looking for this one string. That would probably be easier to write and more robust. When a complete line is received, you would call a function named handleLineReceived() to handle that line. That function would have access to a buffer with the entire line, and it could parse it in whatever way it wants to. (Just be careful that you never write beyond the end of that buffer.)
By the way, I wouldn't be putting logic like that in an ISR. It's generally best to keep ISRs simple and fast. If you are not doing so already, store the byte to a circular buffer in the ISR and then read from the circular buffer in your main loop, and every time you read a byte from the circular buffer then call a function like the rx_data function described above to process the byte.

Send a backslash using C socket for iso8583 message

I am building a POS application verifone (C-language) which should communicate with m2m switch from Morocco but I'm stuck when sending initialization message which should have a backslash like this (08\00) but when sending this I'm having 08\5c00.
It converts backslash by its value in hex(5c). The tool I'm using is socket workbench to simulate the server.
How can I send a backslash without being converted into \5c?
It needs to be done in C Language.
EDIT
This is the data I want to send to the server with the header but when trying to print \00 I get \5C00
sprintf(data,"%s%s%s%s%s%s%s%s%s%s%s%s%s","\x30\x60\x60\x20\x15\x35\x35","\x08",‌"\\00","\x0x00","\x01\x30\x30\x30\x30\xC0\x30\x30\x30\x30","\x97","\\00","\x30\x30"‌,"\x00\x00\x01\x00","\x02",idTerminal,idCommercant,"\x20\x20\x20\xA4\xBC");
If I'm understanding correctly, the first part of your example:
sprintf(data,"%s%s",
"\x30\x60\x60\x20\x15\x35\x35",
"\x08");
is doing exactly what you want. The problem is that on the next %s, you are using "\\00" and you want to server to receive ASCII \00 (which would be 0x5c, 0x30, 0x30), but instead the server reports that it is receiving ASCII \5c00 (which would be 0x5c, 0x,35, 0x43, 0x30, 0x30).
I agree with Klas Lindbäck in that it sounds like the VeriFone terminal is doing the correct thing, but the server is displaying it wrong. There are 2 things I would consider doing in order to troubleshoot this in order to prove that this is correct (and you can do just one or the other or you can do both together).
First: You can use LOG_PRINTF (or print to paper or the screen if you prefer) to print the values of each byte just before you send it off. Below is a quick-and-dirty function I wrote to do just that when I was troubleshooting a similar sort of problem once. Note that I only cared about the beginning of the string (as is the case with you, it seems) so I don't print the end if I run out of buffer space.
void LogDump(unsigned char* input, int expectedLength)
{
#ifdef LOGSYS_FLAG
char buffer[100];
int idx, bfdx;
memset(buffer, 0, sizeof(buffer));
bfdx = 0;
for (idx = 0; idx < expectedLength && bfdx < sizeof(buffer); idx++)
{
//if it is a printable character, print as is
if (input[idx] > 31 && input[idx] < 127)
{
buffer[bfdx++] = (char) input[idx];
continue;
}
//if we are almost out of buffer space, show that we are truncating
// the results with a ~ character and break. Note we are leaving 5 bytes
// because we expand non-printable characters like "<121>"
if (bfdx + 5 > sizeof(buffer))
{
buffer[bfdx++] = '~';
break;
}
//if we make it here, then we have a non-printable character, so we'll show
// the value inside of "<>" to visually denote it is a numeric representation
sprintf(&buffer[bfdx], "<%d>", (int) input[idx]);
//advance bfdx to the next 0 in buffer. It will be at least 3...
bfdx += 3;
//... but for 2 and 3 digit numbers, it will be more.
while (buffer[bfdx] > 0)
bfdx++;
}
//I like to surround my LOG_PRINTF statements with short waits because if there
// is a crash in the program directly after this call, the LOG_PRINTF will not
// finish writing to the serial port and that can make it look like this LOG_PRINTF
// never executed which can make it look like the problem is elsewhere
SVC_WAIT(5);
LOG_PRINTF(("%s", buffer));
SVC_WAIT(5);
#endif
}
Second: try assigning each position in your char array an explicit value. If you already used my LOG_PRINTF suggestion above and found it was not sending what you thought it should be, this would be one way to fix it so that it DOES send EXACTLY what you want. This method is a bit more tedious, but since you are spelling it out each value, anyway, it shouldn't be too much more overhead:
data[0] = 0x30;
//actually, I'd probably use either the decimal value: data[0] = 48;
// or I'd use the ASCII value: data[0] = '0';
// depending on what this data actually represents, either of those is
// likely to be more clear to whomever has to read the code later.
// However, that's your call to make.
data[1] = 0x60;
data[2] = 0x60;
data[3] = 0x20;
data[4] = 0x15;
data[5] = 0x35;
data[6] = 0x35;
data[7] = 0x08;
data[8] = 0x5C; // This is the '\'
data[9] = 0x48; // The first '0'
data[10]= 0x48; // The second '0'
data[11]= 0;
//for starters, you may want to stop here and see what you get on the other side
After you have proven to yourself that it IS or IS NOT the VeriFone code causing the problem, you will know whether you need to focus on the terminal or on the server side.

PIC16f877a switch not reading correctly

I am having a problem with a switch case when using the UART functions. I receive data and store it into the eeprom. I think call a switch statement to see what was sent. I read the eeprom and the information is right but I am just not able to read the right one. It always comes base as an error (default case). I am using Hi-tech C compiler.
unsigned char tempVal;
tempVal = eeprom_read(cmdByteAddr);
switch(tempVal){
//Get temperature
case 30:
writeByte('T');
break;
//Get temp high
case 31:
writeByte('T');
writeByte('H');
break;
//Get temp low
case 32:
writeByte('T');
writeByte('L');
break;
//Get humidity
case 41:
writeByte('H');
break;
//Get humidity high
case 42:
writeByte('H');
writeByte('H');
break;
//Get humidity low
case 43:
writeByte('H');
writeByte('L');
break;
//Error
default:
writeByte('E');
writeByte(eeprom_read(cmdByteAddr));
break;
}
The value returned from eeprom_read() is not one of your cases. The switch() is working correctly. Adjust code to present a more meaningful error using the same switch variable and not another call to eeprom_read().
default:
writeByte('E');
writeByte(tempVal);
break; // Not sure why you want `break` here.
If you still get unsatisfactory results, try unsigned tempVal. Sometimes a compiler get confused, although it should not, on sub-int sized data. You may need to writeUnsigned(tempVal) or its equivalent.
You may want to print cmdByteAddr also. Maybe it is outside the EE range.

Resources