¿ªÔÆÌåÓý

ctrl + shift + ? for shortcuts
© 2025 Groups.io

Re: ADE25MH Mixer - warning #tinysa


 

Here's some cleaner code, a working program for linux to demo strtok()
in a way that I thing it could be used in the tinySA.
Also shows a clean and portable way to read integers.
All of it can gracefully deal with most errors.

Entire thing should port directly to arduino, except arduino has no main() of course.
Calls to printf() are best avoided on something like a Nano, as that function tries to do everything and thus burns a lot of flash.

Also, those on a Nano should avoid the use of floating point, for the same reason.
If only linear sweeps are to be made (not logarithmic), then tinySA.ino need not use any floating point.
(Logarithmic sweeps can also be accomplished using 64 bit long-long fixed point, but that also burns lots of flash.)

Question:? Are logarithmic sweeps a desired feature????


//#################################################
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
?
#define LNBUFSZ 82? ? ? ? ? ? ? // 80 chars plus two for \n and \0
?
char atoix_err = 0;? ? ? ? ? ? ?// Main program can occasionally check this
// Convert string to long in base 8 (0NNN),10 (NNN) or 16 (0xNNN)
long atoix(char *str) {
? ? char *endstr;
? ? long rval;
? ? // errno = 0;
? ? rval = strtol(str, &endstr, 0);
? ? if (*str=='\0' || *endstr!='\0')? ?{
? ? ? ? fprintf(stderr, "ERROR, atoix() expected an octal/decimal/hex number: %s\n", str);
? ? ? ? rval=0;
? ? ? ? atoix_err = 1;? ? ? ? ? // Can set to zero before calling atoix()
? ? }
? ? return(rval);
}

void main() {
? ? char linebuf[LNBUFSZ];
? ? // char* token1;? char* token2; char* token3;
? ? char *token1, *token2, *token3;
? ? int addr, data;
? ? while (1) {
? ? ? ? fgets(linebuf, LNBUFSZ, stdin);? ? ? ? ?// Read chars through a '\n'
? ? ? ? token1 = strtok(linebuf, " \t\n");? ? ? // Find the first token
? ? ? ? if (token1==NULL)? continue;
? ? ? ? if (!strcmp(token1,"x")) {? ? ? ? ? ? ? // Register read/write command
? ? ? ? ? ? token2 = strtok(NULL, " \n\t");? ? ?// Find the second token
? ? ? ? ? ? if (token2 != NULL) {
? ? ? ? ? ? ? ? addr = atoix(token2);
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? printf("%s", "Error, expected one or two args for command x \n");
? ? ? ? ? ? ? ? continue;
? ? ? ? ? ? }
? ? ? ? ? ? token3 = strtok(NULL, " \n\t");? ? ?// Find the third token
? ? ? ? ? ? if (token3 != NULL) {
? ? ? ? ? ? ? ? data = atoix(token3);
? ? ? ? ? ? ? ? printf("regwrite %d %d \n", addr, data);
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? printf("regread %d \n", addr);
? ? ? ? ? ? }
? ? ? ? } else if (!strcmp(token1,"hcf"))? {
? ? ? ? ? ? printf("halt_and_catch_fire() \n");
? ? ? ? } else if (0) {? ? ? ? ?// any other commands go here
? ? ? ? ? ? ? ? // ...
? ? ? ? } else if (!strcmp(token1,"q"))? {
? ? ? ? ? ? exit(0);
? ? ? ? } else {
? ? ? ? ? ? printf("Error, bad command \n");
? ? ? ? }
? ? }
}
//##################################################

Jerry, KE7ER


On Sun, Jan 26, 2020 at 09:11 AM, Jerry Gaffke wrote:

I'm trying to port tinySA.ino over to the RPi.
Appears that the serial command interpreter is highly dependent on the timing of each incoming character.

A better way to do this is to wait for a '\n' character to indicate a complete command before processing it.
And I'd separate each line into tokens with whitespace, either spaces or tabs.
So to write 34 to register 12, the 'x' command becomes the character sequence? "x 12 34\n"
Any extra whitespace is ignored:? "x? ? ? 12? ?\t 34? \t? ?\n"

The C strings library makes this easy, code looks something like this.
Note that each call to strtok() is modifiying linebuf[] by placing a '\0' after the next token,
then returning a pointer for the start of that token within linebuf[]

#include <strings.h>
#define LNBUFSZ 82? ? ? ? ? ? ? // 80 chars plus two for \n and \0

void main() {
? ? char linebuf[LNBUFSZ];?
? ? char* token;
? ? while (1) {
? ? ? ? fgets(linebuf, LNBUFSZ, stdin);? ? // Read chars up to and including the next '\n'
? ? ? ? token = strtok(linebuf, " \t\n");? ? ? ? ? ? ? //? Any whitespace of spaces, tabs or newlines is not a token
? ? ? ? if (!strcmp(token,"x")) {? ? ? ? ? //? "x? addr" to read a register,? ?"x addr data" to write
? ? ? ? ? ? int regaddr, regdata;
? ? ? ? ? ? token = strtok(NULL, " \n\t");? ? // NULL says to continue operating on the same string
? ? ? ? ? ? if (token!=NULL)? regaddr = atoi(token);? else { print("Error, no args to command x \n"); break; }
? ? ? ? ? ? token = strtok(NULL, " \t\n");
? ? ? ? ? ? if (token!=NULL)? regwrite(regaddr, atoi(regdata));? ? else { print(atoi(regread(addr))); }
? ? ? ? } else if (!strcmp(token,"h"))? halt_and_catch_fire();
? ? ? ? } else {
? ? ? ? ? ? ? ? ...
? ? ? ? } else print("Error, bad command \n");
? ? }
}
? ??
Jerry, KE7ER

Join [email protected] to automatically receive all group messages.