Pages: 1 2 [3]   Go Down
 Author Topic: SoftwareSerial magic numbers  (Read 5809 times) 0 Members and 1 Guest are viewing this topic.
Netherlands
Offline
Tesla Member
Karma: 87
Posts: 9368
In theory there is no difference between theory and practice, however in practice there are many...
 « Reply #30 on: January 30, 2013, 02:25:04 pm » Bigger Smaller Reset

Good to hear it works, "outside the lab"
 Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -

Offline
Newbie
Karma: 2
Posts: 2
 « Reply #31 on: February 07, 2013, 05:00:47 pm » Bigger Smaller Reset

Hi robtillaart,

I wondered why a long devision (int32) is needed. I tried to find a solution with int (int16) only. And came up with this precise solution (focus is on rxintra):
Code:
// 8MHZ
int baudrate = (int)speed;

int j=-39 | baudrate;
int m=2* (-baudrate & 2*j | baudrate);
int a=((2*m) & m ) | baudrate;
int rxintra=(-15240-3*a-j)/a-1;
It's precise in a sense that it resembles all table data with 0 difference. (But it's not "linear" in your sense. Instead I call it "weird".)
To make your proof simple I wrote this scetch:
Code:
#include "WProgram.h"

//
// Lookup table
//
typedef struct _DELAY_TABLE
{
long baud;
unsigned short rx_delay_centering;
unsigned short rx_delay_intrabit;
unsigned short rx_delay_stopbit;
unsigned short tx_delay;
} DELAY_TABLE;

//  8 Mhz table
static const DELAY_TABLE table[] PROGMEM =
{
//  baud    rxcenter    rxintra    rxstop  tx
{ 115200,   1,          5,         5,      3,      },
{ 57600,    1,          15,        15,     13,     },
{ 38400,    2,          25,        26,     23,     },
{ 31250,    7,          32,        33,     29,     },
{ 28800,    11,         35,        35,     32,     },
{ 19200,    20,         55,        55,     52,     },
{ 14400,    30,         75,        75,     72,     },
{ 9600,     50,         114,       114,    112,    },
{ 4800,     110,        233,       233,    230,    },
{ 2400,     229,        472,       472,    469,    },
{ 1200,     467,        948,       948,    945,    },
{ 300,      1895,       3805,      3805,   3802,   },
};

int SoftwareSerial_rxintraA(long speed)
{
for (unsigned i=0; i<sizeof(table)/sizeof(table[0]); ++i)
{
if (baud == speed)
{
}
}
return -1;
}

int SoftwareSerial_rxintraB(long speed)
{
long baudrate = speed;
// 8MHZ
int rxintra = 8000000L/(7 * baudrate) - 4;
return rxintra;
}

int SoftwareSerial_rxintraC(long speed)
{
// 8MHZ
int baudrate = (int)speed;

int j=-39 | baudrate;
int m=2* (-baudrate & 2*j | baudrate);
int a=((2*m) & m ) | baudrate;
int rxintra=(-15240-3*a-j)/a-1;
return rxintra;
}

void setup() {
Serial.begin(9600);
Serial.println("baud\tA\tB\tC");
for (unsigned i=0; i<sizeof(table)/sizeof(table[0]); ++i)
{
Serial.print(baud);  Serial.print("\t");
Serial.print(SoftwareSerial_rxintraA(baud));  Serial.print("\t");
Serial.print(SoftwareSerial_rxintraB(baud));  Serial.print("\t");
Serial.print(SoftwareSerial_rxintraC(baud));  Serial.print("\t");
Serial.println();
}
}

void loop() {
}
 « Last Edit: February 08, 2013, 04:56:55 pm by genom2 » Logged

Netherlands
Offline
Tesla Member
Karma: 87
Posts: 9368
In theory there is no difference between theory and practice, however in practice there are many...
 « Reply #32 on: February 08, 2013, 01:40:43 pm » Bigger Smaller Reset

Amazing!
Seen quite some code in my life but this is a very amazing code (+1)

I didn't ran the code but I am wondering how you can represent 115200 in a int16. (you can't) so it is wrapped or truncated .
That result is tweaked by bit manipulation and some magic numbers to the right values.
Can you explain on which principle the math is based? website?

Drawback is its maintainability as it is hard to understand.
Furthermore as the table is only calculated once when begin(speed) is called, I doubt if there is a serious performance gain.

Does your magic code also calculate the intermediate values e.g. a baud rate of 7800 as in the previous post?

 Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -

Offline
Newbie
Karma: 2
Posts: 2
 « Reply #33 on: February 08, 2013, 05:24:19 pm » Bigger Smaller Reset

No, it will not deliver reasonable results for 7800. (At the beginning of this thread you ask for linearity. "weird" functions are not "linear" in your sense.)

I did not invent this "weird" function. Instead a genetic program invented it for me. I fed in the table you gave, reduced to the columns 'baud' and 'rxintra':
Code:
49664   5
57600   15
38400   25
31250   32
28800   35
19200   55
14400   75
9600    114
4800    233
2400    472
1200    948
300     3805
Because it's an int16 genetic programmer I had to truncate 115200 down to 16 Bits which is 49664.

After a while it found a perfect solution (which is equivalent to 0 differences to the given table). I kept it running for a night whilst the genetic programmer delivered even shorter code solutions. At the next morning I picked the best code sequence (so far) which had a codelen of 24:
Code:
a = -39;
a |= x;
j = a;
a += a;
n = a;
a &= 0;
a -= x;
a &= n;
a |= x;
a += a;
m = a;
a += m;
a &= m;
a |= x;
n = a;
a += a;
y= a;
a = -15240;
a -= y;
a -= n;
a -= j;
a = a / n;
y= a;
y--;
Where x is baud and y is rxintra. I manually transformed to, what you already know as:
Code:
// 8MHZ
int baudrate = (int)speed;

int j=-39 | baudrate;
int m=2* (-baudrate & 2*j | baudrate);
int a=((2*m) & m ) | baudrate;
int rxintra=(-15240-3*a-j)/a-1;
 Logged

Netherlands
Offline
Tesla Member
Karma: 87
Posts: 9368
In theory there is no difference between theory and practice, however in practice there are many...
 « Reply #34 on: February 09, 2013, 03:50:45 am » Bigger Smaller Reset

This is real fun!

Do you have a link to that genetic programmer you used?
Or did you write it yourself? post code ?
 Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -

 Pages: 1 2 [3]   Go Up