avr c: creating blink / beep sound based on characters in string - c

I am trying to create beep sound from characters in the string.
Here is the code:
/*
* Buzzer connected to Arduino uno digital pin 13
* Switch connected to digital pin 2
*/
#include <avr/io.h>
#include <util/delay.h>
const int TBEEP = 1000;
const int TBEEEEP = 3500;
const int TGAP = 500;
const int TGAPLETTER = 2000;
int portb = 0x20;
void beep() {
PORTB = ~portb; _delay_ms(TGAP);
PORTB = portb; _delay_ms(TBEEP);
PORTB = ~portb; _delay_ms(TGAP);
}
void beeeep() {
PORTB = ~portb; _delay_ms(TGAP);
PORTB = portb; _delay_ms(TBEEEEP);
PORTB = ~portb; _delay_ms(TGAP);
}
void gapLetter() {
PORTB = ~portb; _delay_ms(TGAPLETTER);
}
void morse_S() {
beep(); beep(); beep();
gapLetter();
}
void morse_M() {
beeeep(); beeeep();
gapLetter();
}
void morse_SMS() {
morse_S(); morse_M(); morse_S();
}
void morse(char theString[]) {
for (int i = 0; theString[i] != '\0'; i++)
{
if(&theString[i] == "S")
morse_S();
else if(&theString[i] == "M")
morse_M();
}
}
int main (void)
{
DDRB = 0xFF;
DDRD = 0x00;
PORTD = 0x04;
while (1) {
if (PIND & 0x04) {
PORTB = ~0x20;
} else {
//morse_SMS(); // it works
morse("SMS"); // this one doesnt work like morse_SMS() PLEASE HELP!
}
}
return 0;
}
In function void morse(char theString[]) {...}, I want to produce beep sound from every character in the string "SMS". Unfortunately, only the last character can make it.
I am using Atmel Studio 6. When I build solution (F7) there is no error but warning which I dont understand (sorry for being such a total noob)
comparison with string literal results in unspecified behavior [-Waddress]
How to force every character to beep one after another?

First of all,
const int TBEEP = 1000;
const int TBEEEEP = 3500;
These made my day. :)
Apart from that, you should really get a good beginner C book. You can't compare strings using the == operator, because that compares pointers, not contents. If you want to compare strings, use the strcmp() function from the C standard library.
But: in your case, you don't want to compare strings. You want to compare characters. And that can be done with ==, just dereference the character pointer to obtain the actual character, and compare it with a character literal, not with a string literal:
if (theString[i] == 'S')
morse_S();
else if (theString[i] == 'M')
morse_M();
Oh, and probably you want to avoid that enormous chained if...else if...else monster. Assuming UTF-8 or at least ASCII encoding, where the character codes of English letters are in alphabetical order:
void (*morse_funcs[26])();
morse_funcs[0] = morse_A;
morse_funcs[1] = morse_B;
// ...
morse_funcs[25] = morse_Z;
// ...
void morse(const char *s)
{
while (*s)
morse_funcs[tolower(*s++) - 'a']();
}
Also, notice how I changed char * into const char *. If you don't modify a string, tell the compiler that you don't intend to modify it, so you can safely pass in string literals as well.
Even better: don't use a table of function pointers, but a table of Morse codes. Like this:
const char *mcodes[26] = {
".-", // 'a'
"-...", // 'b'
// etc...
"--.." // 'z'
};
void do_morse(const char *code)
{
while (*code)
if (*code++ == '-')
beeeep();
else
beep();
}
void morse(const char *s)
{
while (*s)
do_morse(mcodes[tolower(*s++) - 'a']);
}

Try this:
void morse(char theString[]) {
for (int i = 0; theString[i] != '\0'; i++)
{
if(theString[i] == 'S')
morse_S();
else if(theString[i] == 'M')
morse_M();
}
}

Related

String parsing, turn LED on/off based on received serial data

I am receiving in the serial port from python a string in this format (0,77,88,55).
I have the first number randomized to either be 0 or 1, the rest are fixed.
import random
import serial
import time
last_time = 0
test_list = [0,1]
serialSTM32 = serial.Serial('COM22',9600,writeTimeout=0)
while True:
if (time.time() - last_time) > 2:
random_num = random.choice(test_list)
#string = str(random_num)
string = "(" + str(random_num) + "," + "77" + "," + "88" + "," + "55" + ")"
serialSTM32.write(string.encode('utf-8'))
print(string)
last_time = time.time()
serialSTM32.flushInput()
The STM32 MCU is receiving through the virtual serial COM port the data through a variable in the "usbd_cdc_if.c" file:
uint8_t bufferVariable = 0;
static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
{
USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
USBD_CDC_ReceivePacket(&hUsbDeviceFS);
bufferVariable = Buf[0];
return (USBD_OK);
}
The bufferVariable is passed to the "main.c" file using:
extern uint8_t bufferVariable;
The "main.c" is then parsing the data, splitting the data and placing the first number which is '0' or '1' in a variable named "first", the second number which is '77' in a variable named "second" etc.
I am taking the "first" variable to see if it is '1' to turn on the LED, but if it is '0' to turn off the LED.
Program waits for start market "(" and keeps reading until it reaches end marker ")", then parses the data in between the two. **Works well on Arduino from parsing tutorial a while back, i converted everything to work on STM32 MCU....
**For this STM32 controller, previously, I tested without the parsing, only receiving '1' or '0' through serial to turn on/off the LED which works.....but now I am using the format (0,77,88,55) which includes parsing the data then getting the value extracted from that format. **This part is not working....LED does not turn on or off.
"main.c" file code:
#define buffer_size 40
char input_buffer[buffer_size];
const char start_marker = '(';
const char end_marker = ')';
uint8_t bytes_received = 0;
uint8_t read_in_progress = 0;
char* grab_value(char *data, char separator, int index) {
int found = 0;
int string_index[] = { 0, -1 };
int maximum_index = strlen(data) - 1;
for (int i = 0; i <= maximum_index && found <= index; i++) {
if (data[i] == separator || i == maximum_index) {
found++;
string_index[0] = string_index[1] + 1;
string_index[1] = (i == maximum_index) ? i + 1 : i;
}
}
if (found > index) {
data[string_index[1]] = '\0';
return &data[string_index[0]];
} else {
return NULL;
}
}
int first, second, third, fourth;
extern uint8_t bufferVariable;
int main(void) {
while (1) {
if (bufferVariable == end_marker) {
read_in_progress = 0;
input_buffer[bytes_received] = '\0';
}
if (read_in_progress) {
input_buffer[bytes_received++] = bufferVariable;
if (bytes_received == buffer_size) {
bytes_received = buffer_size - 1;
}
}
if (bufferVariable == start_marker) {
bytes_received = 0;
read_in_progress = 1;
}
char *str_first = grab_value(input_buffer, ',', 0);
char *str_second = grab_value(input_buffer, ',', 1);
char *str_third = grab_value(input_buffer, ',', 2);
char *str_fourth = grab_value(input_buffer, ',', 3);
if (str_first) {
first = atoi(str_first);
}
if (str_second) {
second = atoi(str_second);
}
if (str_third) {
third = atoi(str_third);
}
if (str_fourth) {
fourth = atoi(str_fourth);
}
printf("first: %d\n", first);
if (first == '0') {
HAL_GPIO_WritePin(GPIOK, GPIO_PIN_3, GPIO_PIN_SET);
} else if (first == '1') {
HAL_GPIO_WritePin(GPIOK, GPIO_PIN_3, GPIO_PIN_RESET);
}
}
}
first == '0'
It is completely wrong. '0' is not zero integer value only 48 in ASCII representing the character '0'.
Do not reinvent the wheel.
After the whole sting reception simply:
if(sscanf(inputBuffer, "(%d,%d,%d,%d)", &first, &second, &third, &fourth) == 4)
{
if(!first) HAL_GPIO_WritePin(GPIOK, GPIO_PIN_3, GPIO_PIN_SET);
else HAL_GPIO_WritePin(GPIOK, GPIO_PIN_3, GPIO_PIN_RESET);
}
STM32 uCs have much more resources than AVR uCs used in Arduino and you do not need any "tricks"
Only make sure that inputBuffer is null character terminated
Disclaimer, this is my personal preference:
For embedded, you should never use blocking I/O, always buffered, interrupt-driven I/O. I cannot say a single thing in favor of blocking I/O except it's simpler.
You say the problem is, that the LED doesn't toggle.
Let's look at the facts.
This check controls whether or not to toggle the LED:
if (first == '0') {
HAL_GPIO_WritePin(GPIOK, GPIO_PIN_3, GPIO_PIN_SET);
} else if (first == '1') {
HAL_GPIO_WritePin(GPIOK, GPIO_PIN_3, GPIO_PIN_RESET);
}
I notice that you're comparing an integer with the char-values for 0 and 1 and not the integer values. You're essentially checking if first == 48/49 instead of 0/1 (see integer values https://www.asciitable.com/)
At the same time, you're converting the received string to an integer by doing
first = atoi(str_first);
Compare first against 0 or 1 instead of '0' and '1' (which are 48 and 49 respectively).

How to continually print output inside a switch statement?

I have been trying to continually print the PWM output of pin 3 inside the switch statement condition but it only prints once. Can I continually print it in serial monitor until it meets the second conditon? or use a while loop? or a if else ?
Here is my code I also have a code with a similar function but it uses if else but still it only prints once
void loop() {
// if there's any serial available, read it:
while (Serial.available() > 0) {
int InitVal = Serial.parseInt();
int red = Serial.parseInt();
switch(InitVal) {
case 1:
if (Serial.read() == '\n') {
analogWrite(redPin, red);
Serial.println(red);
Serial.write(red);
}
break;
case 0:
analogWrite(redPin, 0);
Serial.println(0);
Serial.write(0);
break;
}
}
}
I'am planning to inter-phase this with a GUI . A GUI sends ascii to the arduino reads it then sends the output value to the GUI.
Example
1.GUI sends [1,123] : 1 = the trigger point for the switch statement ; 123 = PWM value.
Arduino receives instructions and it prints out the pwm value
GUI receives pwm value and displays it
Revised code: Stuck at the last while loop maybe i could use a threading function in arduino so that the last while loop would be satisfied/dissatisfied?
void loop() {
int InitVal = 0;
// if there's any serial available, read it:
while (Serial.available() > 0) {
int InitVal = Serial.parseInt();
int red = Serial.parseInt();
switch(InitVal) {
case 1:
if (Serial.read() == '\n') {
InitVal = 1;
//analogWrite(redPin, red);
//Serial.println(red);
// Serial.write(red);
}
break;
case 0:
InitVal = 0;
//analogWrite(redPin, 0);
//Serial.println(0);
//Serial.write(0);
break;
}
if (InitVal) /* when enabled, blink leds */ {
delay(20);
while (InitVal == 1) /* loop forever */{
Serial.println(red);
Serial.write(red);
delay(20);
}
}
}
}
I discarded Serial.parseInt() function, removed the switch statments and followed #Arno Bozo advise on serial listening while following this tutorial on http://forum.arduino.cc/index.php?topic=396450.0
I came up with what I want and here is the code
const int redPin = 3;
const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars]; // temporary array for use when parsing
// variables to hold the parsed data
boolean newData = false;
int InitVal = 0; // change to init value or red
int red = 0;
void setup() {
// initialize serial:
Serial.begin(9600);
// make the pins outputs:
pinMode(redPin, OUTPUT);
}
void loop() {
recvWithStartEndMarkers();
if (newData == true) {
strcpy(tempChars, receivedChars);
// this temporary copy is necessary to protect the original data
// because strtok() used in parseData() replaces the commas with \0
parseData();
One();
newData = false;
}
else {
Zero();
}
}
///////////////////// ///////////////////// /////////////////////
void recvWithStartEndMarkers() {
static boolean recvInProgress = false;
static byte ndx = 0;
char startMarker = '<';
char endMarker = '>';
char rc;
while (Serial.available() > 0 && newData == false) {
rc = Serial.read();
if (recvInProgress == true) {
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = '\0'; // terminate the string
recvInProgress = false;
ndx = 0;
newData = true;
}
}
else if (rc == startMarker) {
recvInProgress = true;
}
}
}
///////////////////// ///////////////////// /////////////////////
void parseData() { // split the data into its parts
char * strtokIndx; // this is used by strtok() as an index
strtokIndx = strtok(tempChars,","); // get the first part - the string
InitVal = atoi(strtokIndx); // copy it to messageFromPC
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
red = atoi(strtokIndx); // convert this part to an integer
}
///////////////////// ///////////////////// /////////////////////
void One() {
if (InitVal == 0){
delay(20);
Serial.println(0);
delay(20);
}
}
///////////////////// ///////////////////// /////////////////////
void Zero() {
if (InitVal == 1){
delay(20);
Serial.println(red);
delay(20);
}
}
In Summary the code works like this
1.In serial monitor send this <1,123> : 1 = the trigger point for the switch statement ; 123 = PWM value.
Arduino receives instructions and it prints out the pwm value
If you send <0,123> it prints a zero once
I post a refined code here. The architecture may be reused for serial treatment. I have written it as an example for people I meet and who are learning with arduino.
I have made comments and explanation of ways to avoid delay. Here it is used to print current value of pwm every 1s, without stopping with a delay(1000).
#include <Arduino.h>
// with schedule(f,i) , the function f() will be called every i ms
// schedule(f,i) lines are put in loop() function
// f is of type void f(void)
#define schedule(f,i) {static unsigned long l=0;unsigned long c=millis();if((unsigned long)(c-l)>=i){l=c;f();}}
const int ledPin = 13;
void setup() {
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
}
boolean newCommandHasArrived=false, newParsedCommand=false;
String personalSerialBuffer=""; // char[] would be better; but String are so convenient
enum ECommand {ecmdNoPwm=0, ecmdPwm=1, ecmdBad=10 };
ECommand cmd=ecmdNoPwm;
int cmdArg=0;
boolean readSerialBuffer(String &personalSerialBuffer);
boolean parseCommand(String &apersonalSerialBuffer, ECommand &acmd, int &acmdArg);
void executeCommand(ECommand acmd, int &acmdArg);
void printCurrentValue() {Serial.println(String("cval:") + cmdArg);}
void loop() {
// transfer serial buffer in personal buffer
newCommandHasArrived = readSerialBuffer(personalSerialBuffer);
if (newCommandHasArrived) {
newCommandHasArrived = false;
newParsedCommand = parseCommand(personalSerialBuffer, cmd, cmdArg);
}
if (newParsedCommand) {
newParsedCommand = false;
executeCommand(cmd, cmdArg);
}
// I print current value every 1000ms
//delay(1000); // you can often use delay without pb, but it is a bad usage
// Here I provide you with a quick way to execute a task every 1000ms
{
const unsigned long delayBetweenExecution=1000;
static unsigned long lastTime=0;
unsigned long current = millis();
// note that C++ says that overflow on unsigned is well defined
// it calculates modulo arithmetic
if ((unsigned long)(millis() - lastTime) >= delayBetweenExecution) {
lastTime = current;
Serial.println(String("cval:") + cmdArg);
}
}
// We can make it shorter thanks to a macro:
// but you have to define a void function(void) that uses only global variable
// because it has no argument :
// void printCurrentValue() {Serial.print(String("cval:") + cmdArg);}
//schedule(printCurrentValue, 1000);
}
boolean readSerialBuffer(String &personalSerialBuffer) {
if (Serial.available() > 0) {
personalSerialBuffer.concat(Serial.readString());
}
// the frame is considered finished, if it ends with \n
if (personalSerialBuffer.endsWith("\n"))
return true;
else
return false;
}
boolean parseCommand(String &apersonalSerialBuffer, ECommand &acmd, int &acmdArg) {
// format [ 1, 123]\n
// I omit [ then I read first int : 1
// Note: I cannot detect if no int is found because it will return 0 that is a valid cmd
int readCmd = apersonalSerialBuffer.substring(1).toInt();
// conversion readCmd to acmd
switch (readCmd) {
case 0:
acmd = ecmdNoPwm; break;
case 1:
acmd = ecmdPwm; break;
default:
Serial.println(String("new command unknown: ") +
apersonalSerialBuffer);
apersonalSerialBuffer = "";
return false;
}
// find beginning of 2nd part, separated by ','
int sepPos = apersonalSerialBuffer.indexOf(',');
// no ',' : indexOf returns -1
if (sepPos == -1) {
Serial.println(String("new command could not be parsed: ") +
apersonalSerialBuffer);
apersonalSerialBuffer = "";
return false;
}
// Note: I cannot detect if no int is found because it will return 0 that is a valid cmd
acmdArg = apersonalSerialBuffer.substring(sepPos+1).toInt();
// All is fine
// I have to reset buffer before leaving
apersonalSerialBuffer = "";
return true;
}
void executeCommand(ECommand acmd, int &acmdArg) {
switch(acmd) {
case ecmdNoPwm:
// I erase acmdArg
acmdArg = 0;
analogWrite(ledPin, acmdArg);
Serial.println("cmd no pwm");
break;
case ecmdPwm:
analogWrite(ledPin, acmdArg);
Serial.print("cmd pwm:"); Serial.println(acmdArg);
break;
default:
analogWrite(ledPin, 0);
Serial.println("Bad cmd");
}
}

receive/transmit over rs232 with arm lpc2148 on sparkfun logomatic

I am trying to program the logomatic by sparkfun, and yes I have used their forum with no responses, and having some issues. I am trying to send characters to the UART0 and I want the logomatic to respond with specific characters and not just an echo. For example, I send 'ID?' over the terminal (using RealTerm), and the logomatic sends back '1'. All it will so now is echo.
I am using c with programmers notepad with the WinARM toolchain. The following snippet is from the main.c file. I only included this, because I am fairly certain that this is where my problem lies
void Initialize(void)
{
rprintf_devopen(putc_serial0);
PINSEL0 = 0xCF351505;
PINSEL1 = 0x15441801;
IODIR0 |= 0x00000884;
IOSET0 = 0x00000080;
S0SPCR = 0x08; // SPI clk to be pclk/8
S0SPCR = 0x30; // master, msb, first clk edge, active high, no ints
}
Notice the rprintf_devopen function, below is from the rprintf.c file, and due to my mediocre skills, I do not understand this bit of code. If I comment out the rprintf_devopen in main, the chip never initializes correctly.
static int (*putcharfunc)(int c);
void rprintf_devopen( int(*put)(int) )
{
putcharfunc = put;
}
static void myputchar(unsigned char c)
{
if(c == '\n') putcharfunc('\r');
putcharfunc(c);
}
Now, below is from the serial.c file. So my thought was that I should be able to just call one of these putchar functions in main.c and that it would work, but it still just echoes.
int putchar_serial0 (int ch)
{
if (ch == '\n')
{
while (!(U0LSR & 0x20));
U0THR = CR; // output CR
}
while (!(U0LSR & 0x20));
return (U0THR = ch);
}
// Write character to Serial Port 0 without \n -> \r\n
int putc_serial0 (int ch)
{
while (!(U0LSR & 0x20));
return (U0THR = ch);
}
// Write character to Serial Port 1 without \n -> \r\n
int putc_serial1 (int ch)
{
while (!(U1LSR & 0x20));
return (U1THR = ch);
}
void putstring_serial0 (const char *string)
{
char ch;
while ((ch = *string))
{
putchar_serial0(ch);
string++;
}
}
I have tried calling the different putchar functions in main, also with the rprintf_devopen. Still just echoes. I have altered the putchar functions and still just echoes. I have tried just writing to the U0THR register in main.c and no luck. Keep in mind that I am still a student and my major is electrical engineering, so the only programming classes that I have taken are intro to c, and an intro to vhdl. I am more of a math and physics guy. I was working on this for an internship I was doing. The internship ended, but it just bugs me that I cannot figure this out. Honestly, working on this program taught me more that the c class that I took. Anyways, I appreciate any help that can be offered, and let me know if you want to see the entire code.
Below is an update to the question. This function is in main.c
static void UART0ISR(void)
{
char temp;
trig = 13; //This is where you set the trigger character in decimal, in this case a carriage return.
temp = U0RBR; //U0RBR is the receive buffer on the chip, refer to datasheet.
if(temp == query1[counter1]) //This segment looks for the characters "ID?" from the U0RBR
{ //query1 is defined at the top of the program
counter1++;
if(counter1 >= 3)
{
flag1 = 1; //This keeps track of whether or not query1 was found
counter1 = 0;
stat(1,ON);
delay_ms(50);
stat(1,OFF);
RX_in = 0;
temp = 0;
//rprintf("\n\rtransmission works\n");
putc_serial1(49);
}
}
if(temp == query2[counter2] && flag1 == 1) //This segment looks for "protov?" from the U0RBR, but only after query1 has been found
{
counter2++;
if(counter2 >= 7)
{
flag2 = 1; //This keeps track of whether or not query2 was found
counter2 = 0;
stat(1,ON);
delay_ms(50);
stat(1,OFF);
RX_in = 0;
temp = 0;
putc_serial1(49);
}
}
if(temp == stop[counter3]) //This if segment looks for certain characters in the receive buffer to stop logging
{
counter3++;
if(counter3 >= 2)
{
flagstop = 1; //This flagstop keeps track of whether or not stop was found. When the stop characters are found,
flag1 = 0; //the query1 and query2 flags will be reset. So, in order to log again these queries must be sent again
flag2 = 0; //this may seem obvious, but deserves mention.
counter3 = 0;
stat(1,ON);
delay_ms(500);
stat(1,OFF);
RX_in = 0;
temp = 0;
}
flagstop = 0; //Reset the stop flag in order to wait once again for the query 1&2
}
if(RX_in == 0)
{
memset (RX_array1, 0, 512); // This clears the RX_array to make way for new data
memset (RX_array2, 0, 512);
}
if(RX_in < 512 && flag1 == 1 && flag2 == 1) //We cannot log data until we see both flags 1 & 2 and after we see these flags,
{ //we must then see the trigger character "carriage return"
RX_array1[RX_in] = temp;
RX_in++;
if(temp == trig)
{
RX_array1[RX_in] = 10; // delimiters
log_array1 = 1;
RX_in = 0;
}
}
else if(RX_in >= 512 && flag1 == 1 && flag2 == 1) //This else if is here in case the RX_in is greater than 512 because the RX_arrays are defined to
{ //be of size 512. If this happens we don't want to lose data, so we must put the overflow into another register.
RX_array2[RX_in - 512] = temp;
RX_in++;
RX_array1[512] = 10; // delimiters
RX_array1[512 + 1] = 13;
log_array1 = 1;
if(RX_in == 1024 || temp == trig)
{
RX_array2[RX_in - 512] = 10; // delimiters
log_array2 = 1;
RX_in = 0;
}
}
temp = U0IIR; // have to read this to clear the interrupt
VICVectAddr = 0;
}

UTF-8 to unicode converter for embeded system display

I have an embedded system that gets UTF-8 encoded data to display via UPNP. The display device has the ability to display characters. I need a way to convert the UTF-8 data I recieve via UPNP to unicode. The display is on a PIC, and it is sent data via a UPNP bridge running linux. Is there a simple way to do the conversion before I send it to the display board in linux?
If you have a real operating system and hosted C environment at your disposal, the best approach would be to simply ensure that your program runs in a locale that uses UTF-8 as its encoding and use mbrtowc or mbtowc to convert UTF-8 sequences to Unicode codepoint values (wchar_t is a Unicode codepoint number on Linux and any C implementation that defines __STDC_ISO_10646__).
If you do want to skip the system library routines and do UTF-8 decoding yourself, be careful. I once did a casual survey using Google code search and found that somewhere between 1/3 and 2/3 of the UTF-8 code out in the wild was dangerously wrong. Here is a fully correct, fast, and simple implementation I would highly recommend:
http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
My implementation in musl is somewhat smaller in binary size and seems to be faster, but it's also a bit harder to understand.
To convert an array of bytes encoded as UFT-8 into an array of Unicode code points:
The trick is to detect various encoding mistakes.
#include <limits.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
typedef struct {
uint32_t UnicodePoint; // Accumulated code point
uint32_t Min; // Minimum acceptable codepoint
int i; // Index of char/wchar_t remaining
bool e; // Error flag
} UTF_T;
static bool IsSurrogate(unsigned c) {
return (c >= 0xD800) && (c <= 0xDFFF);
}
// Return true if more bytes needed to complete codepoint
static bool Put8(UTF_T *U, unsigned ch) {
ch &= 0xFF;
if (U->i == 0) {
if (ch <= 0x7F) {
U->UnicodePoint = ch;
return false; /* No more needed */
} else if (ch <= 0xBF) {
goto fail;
} else if (ch <= 0xDF) {
U->Min = 0x80;
U->UnicodePoint = ch & 0x1F;
U->i = 1;
} else if (ch <= 0xEF) {
U->Min = 0x800;
U->UnicodePoint = ch & 0x0F;
U->i = 2;
} else if (ch <= 0xF7) {
U->Min = 0x10000;
U->UnicodePoint = ch & 0x07;
U->i = 3;
} else {
goto fail;
}
return true; /* More needed */
}
// If expected continuation character missing ...
if ((ch & (~0x3F)) != 0x80) {
goto fail;
}
U->UnicodePoint <<= 6;
U->UnicodePoint |= (ch & 0x3F);
// If last continuation character ...
if (--(U->i) == 0) {
// If codepoint out of range ...
if ((U->UnicodePoint < U->Min) || (U->UnicodePoint > 0x10FFFF)
|| IsSurrogate(U->UnicodePoint)) {
goto fail;
}
return false /* No more needed */;
}
return true; /* More needed */
fail:
U->UnicodePoint = -1;
U->i = 0;
U->e = true;
return false /* No more needed */;
}
/* return 0:OK, else error */
bool ConvertUTF8toUnicodeCodepoints(const char *UTF8, size_t Length,
uint32_t *CodePoints, size_t *OutLen) {
UTF_T U = { 0 };
*OutLen = 0;
for (size_t i = 0; i < Length;) {
while (Put8(&U, UTF8[i++])) {
// Needed bytes not available?
if (i >= Length) {
return true;
}
}
if (U.e) break;
CodePoints[(*OutLen)++] = U.UnicodePoint;
}
return U.e;
}
This is based on some old code, please advise as it may not be up to current standards.
Not the prettiest with goto and magic numbers.
What is nice about this approach is rather than CodePoints[(*OutLen)++] = U.UnicodePoint for consuming the codepoint, if one wanted to extract UTF16 (BE or LE), one could easily write consumer code for the UTF_T block and not need to change to the UTF8 -> codepoint part.
I would use the Unicode manipulation functions of GLib, a LGPL-licensed utility library. It sounds like g_utf8_to_ucs4() is what you are looking for.

Bluetooth communications with C

I want to write 2 programs with C , one work on Robot1, the other work on Robot2.
So I want the program to send a signal from Robot1 via Bluetooth to Robot2 and Robot2 handles and accepts this signal (message)and reply to Robot1.
how to code this?
please I need any kind of help.
API OF my Robots:
/* function for serial communication */
void SerWrite(unsigned char *data,unsigned char length)
{
unsigned char i = 0;
UCSRB = 0x08; // enable transmitter
while (length > 0) {
if (UCSRA & 0x20) { // wait for empty transmit buffer
UDR = data[i++];
length --;
}
}
while (!(UCSRA & 0x40));
for (i = 0; i < 0xFE; i++)
for(length = 0; length < 0xFE; length++);
}
void SerRead(unsigned char *data, unsigned char length,unsigned int timeout)
{
unsigned char i = 0;
unsigned int time = 0;
UCSRB = 0x10; // enable receiver
/* non blocking */
if (timeout != 0) {
while (i < length && time++ < timeout) {
if (UCSRA & 0x80) {
data[i++] = UDR;
time = 0;
}
}
if (time > timeout) data[0] = 'T';
}
/* blocking */
else {
while (i < length) {
if (UCSRA & 0x80)
data[i++] = UDR;
}
}
}
-------------------------------------------------------------------------------------------Bluetooth Model...code...
#include "asuro.h"
void Sekunden(unsigned int s) //Unterprogramm für Sekundenschleife (maximal 65s)
{
unsigned int t; // Definierung t als Vorzeichenloses int
for(t=0;t<s*1000;t++) // 1000*s durchlaufen
{
Sleep(72); // = 1ms
}
}
int main (void)
{
unsigned char daten[2], merker=0; //Speicher bereitstellen, merker für start/stop
Init();
UBRRL = 0x67; //4800bps # 8MHz
Marke: // Endlosschleife
SerRead(daten,1,0); // Daten einlesen
switch (daten[0]) //und verarbeiten
{
case 0x38: MotorDir(FWD,FWD); // Vorwärts
MotorSpeed(merker*120,merker*120);
SerWrite("Vor \r",22);
break;
case 0x36: MotorDir(FWD,FWD); // Links
MotorSpeed(merker*120,merker*170);
SerWrite("Links \r",22);
break;
case 0x37: MotorDir(RWD,RWD); // Rückwärts
MotorSpeed(merker*120,merker*120);
SerWrite("Zurueck \r",22);
break;
case 0x34: MotorDir(FWD,FWD); // Rechts
MotorSpeed(merker*170,merker*120);
SerWrite("Rechts \r",22);
break;
case 0x35: if(merker==1)
{
MotorDir(FREE,FREE);// Stop
MotorSpeed(0,0);
SerWrite("Stop \r",22);
merker=0;
break;
}
else
{
MotorDir(FWD,FWD);// Start
MotorSpeed(120,120);
SerWrite("Start \r",22);
merker=1;
break;
}
}
i want to run this programm on my Robot.
Robot 2 needs to call SerRead with, lets say, a pointer to an empty buffer (length one or so), length one and zero as timeout. Afterwards, let it call SerWrite with a pointer to your buffer and length one.
Robot 1 should first call SerWrite with one byte of data and then wait for the result of a call to SerRead.

Resources