BricxCC/NBC test release 2011-07-19
BricxCC/NBC test release 2011-07-19
I have uploaded a new test release zip with updated help files and pdf documentation. I am updating the online html pages at the present time. There are additional optimizations performed at level 3 and 4. Please test at level 3 for sure (the new optimizations) and at level 4 (optimizations that were already in the compiler but formerly at level 3) if you are daring. I have also optimized the optimizations so the compiler should feel a bit faster than it used to when you are using optimization levels > 1.
I have run a number of regression tests but it is not impossible that I have overlooked something. Please let me know if you run into any regressions. I hope to have this all rolled up into an official release later this week. If I get some help testing at optimization level 3 I may move those into level 2 if there do not appear to be any regressions/defects.
Here are the release notes for the current NBC and BricxCC test releases:
version 3.3.8.10
---------------
- NBC 1.2.1.r5
- Changed ROPS line highlighting to only be on while stepping through the code line by line.
- Watch window changes and joystick tool enhancements
- Fixed incorrect gettick help content
- Help updates for JoystickMessageType, JoystickMessageRead, SysRandomEx, rand, and srand API functions.
- Fixed text clipping defect in enhanced NBC/NXC firmware 1.31
- Added a new random number generator system call to enhanced NBC/NXC firmware 1.31
- ARROP enhanced firmware opcode fixes for floating point arrays
- Changed ARROP to base float/signed/unsigned calculations on output type rather than input type
- RS485 firmware changes to report more information from CommHSCheckStatus system call
Version 1.2.1.r5 (2011-07-19)
-----------------------------
- Cross platform updates for Linux (FPC/Lazarus)
- Added support for Dexter Industries DiGPS sensor
- Fixed typo defect in glPyramid API function
- Fixed defect with the inline keyword being used with a function prototype.
- Fixed defect with uninitialized strings not being valid strings (i.e., they are
not null terminated) which crashes string opcodes in the firmware.
- Changed the way that I2CBytes works (readlsbytes* in nxtdefs.h) so that there
is not a minimum of 15 ms overhead.
- Fixed infinite loop bug in structure declaration when unexpected characters are present.
- Fixed definition for several Remote* API functions which sent direct/system commands
to other NXT devices via Bluetooth or RS-485
- Fixes for rand() and RAND_MAX and _Random in NXTDefs.h
- Test program additions and updates
- Changes to PF Combo and Raw API functions.
- Added JoystickMessageType structure and JoystickMessageRead API function.
- Added support for new RandomEx system call with rand() and srand()
- Changed code in doAsm to set the statement type if the block contains
__GENRETVAL__ so that the RegisterName function returns the right register name.
- Changed __SeedRandomEx to reset the ReSeed flag back to FALSE so that the
__RandomEx function does not have to set it before calling the RandomEx system call function.
- Added support for static variables.
- Changed RS485CheckStatus, RS485DataAvailable, and RS485SendingData API functions to return
byte values (number of bytes being sent or available to read) rather than booleans.
- Updates to example programs for RS485 firmware fixes and API changes as well as the new
rand() and srand() API functions.
- Fixed bug with assigning a negative constant to an unsigned long variable.
- Fixed bug where static variables in inline functions were not being statically initialized.
- Added BranchComp, BranchTest, ArrayIndex, and ArrayReplace macros to NXCDefs.h
- Modified code generated for the repeat loop so that it has less overhead
- Changes to fix problems with using the wrong stack variables for unsigned types
- Added support for nested compif/compelse/compend compiler directives.
- Changes to speed up code optimizations.
- Additional code optimizations for array helper temporaries and other opcodes.
I have run a number of regression tests but it is not impossible that I have overlooked something. Please let me know if you run into any regressions. I hope to have this all rolled up into an official release later this week. If I get some help testing at optimization level 3 I may move those into level 2 if there do not appear to be any regressions/defects.
Here are the release notes for the current NBC and BricxCC test releases:
version 3.3.8.10
---------------
- NBC 1.2.1.r5
- Changed ROPS line highlighting to only be on while stepping through the code line by line.
- Watch window changes and joystick tool enhancements
- Fixed incorrect gettick help content
- Help updates for JoystickMessageType, JoystickMessageRead, SysRandomEx, rand, and srand API functions.
- Fixed text clipping defect in enhanced NBC/NXC firmware 1.31
- Added a new random number generator system call to enhanced NBC/NXC firmware 1.31
- ARROP enhanced firmware opcode fixes for floating point arrays
- Changed ARROP to base float/signed/unsigned calculations on output type rather than input type
- RS485 firmware changes to report more information from CommHSCheckStatus system call
Version 1.2.1.r5 (2011-07-19)
-----------------------------
- Cross platform updates for Linux (FPC/Lazarus)
- Added support for Dexter Industries DiGPS sensor
- Fixed typo defect in glPyramid API function
- Fixed defect with the inline keyword being used with a function prototype.
- Fixed defect with uninitialized strings not being valid strings (i.e., they are
not null terminated) which crashes string opcodes in the firmware.
- Changed the way that I2CBytes works (readlsbytes* in nxtdefs.h) so that there
is not a minimum of 15 ms overhead.
- Fixed infinite loop bug in structure declaration when unexpected characters are present.
- Fixed definition for several Remote* API functions which sent direct/system commands
to other NXT devices via Bluetooth or RS-485
- Fixes for rand() and RAND_MAX and _Random in NXTDefs.h
- Test program additions and updates
- Changes to PF Combo and Raw API functions.
- Added JoystickMessageType structure and JoystickMessageRead API function.
- Added support for new RandomEx system call with rand() and srand()
- Changed code in doAsm to set the statement type if the block contains
__GENRETVAL__ so that the RegisterName function returns the right register name.
- Changed __SeedRandomEx to reset the ReSeed flag back to FALSE so that the
__RandomEx function does not have to set it before calling the RandomEx system call function.
- Added support for static variables.
- Changed RS485CheckStatus, RS485DataAvailable, and RS485SendingData API functions to return
byte values (number of bytes being sent or available to read) rather than booleans.
- Updates to example programs for RS485 firmware fixes and API changes as well as the new
rand() and srand() API functions.
- Fixed bug with assigning a negative constant to an unsigned long variable.
- Fixed bug where static variables in inline functions were not being statically initialized.
- Added BranchComp, BranchTest, ArrayIndex, and ArrayReplace macros to NXCDefs.h
- Modified code generated for the repeat loop so that it has less overhead
- Changes to fix problems with using the wrong stack variables for unsigned types
- Added support for nested compif/compelse/compend compiler directives.
- Changes to speed up code optimizations.
- Additional code optimizations for array helper temporaries and other opcodes.
Multi-platform LEGO MINDSTORMS programming
http://bricxcc.sourceforge.net/
http://bricxcc.sourceforge.net/
Re: BricxCC/NBC test release 2011-07-19
new speed test.
pure C- code: much faster,
asm-code: mostly file error -1 at optimization levels >1
https://sourceforge.net/apps/phpbb/mind ... 9187#p9187
pure C- code: much faster,
asm-code: mostly file error -1 at optimization levels >1
https://sourceforge.net/apps/phpbb/mind ... 9187#p9187
Re: BricxCC/NBC test release 2011-07-19
with this code:
old + new versions file error -1 from opt. lev. >= 3
new: compared to old version 20110702
//fw 20110702 Opt Lev 0: file error -1
//fw 20110702 Opt Lev 1: 221471
//fw 20110702 Opt Lev 2: 154688
//fw 20110702 Opt Lev 3: 154702
//fw 20110702 Opt Lev 4: 155658
//fw 20110719 Opt Lev 1: 216,025
//fw 20110719 Opt Lev 2: 151,912
//fw 20110719 Opt Lev 3: file error -1
//fw 20110719 Opt Lev 4: file error -1
old + new versions file error -1 from opt. lev. >= 3
Code: Select all
/////////////////////////////////////////////////////////////////////////////
// TamTam.c
// Version 1.0.8.0 "Dijkstra"
// virtuelle Wegsuche auf dem Display
//***************************************************************************
// getestet mit NXC firmware 1.28 enhanced
//***************************************************************************
// der A* (A-Stern, a-star) - Algorithmus fuer den NXT
// zur Wegsuche und Navigation an Hindernissen vorbei
//***************************************************************************
// hier in der Variante nach Dijkstra
// (keine geschaetzten heuristischen Kosten H, also H=0 => F=G!
//
// 1.0.8 eues Array Handling (=> get/free mem)
// 1.0.4 am Schluss werden Routenanweisungen erstellt
// 1.0.1 erkennt, wenn kein Weg zum Ziel existiert
// 0.8.9 Suchrichtung optimiert: direkte Wege werden sehr schnell gefunden
// 0.3.8 Kurse optimiert: Kurs-Aenderungen verursachen hoehere Kosten
// 0.2.9 schneiden von Hindernis-Kanten wird vermieden
// (c) H. W. 2008
/////////////////////////////////////////////////////////////////////////////
#define ArrayInit2D(bar, tmp, init_val, dimx, dimy) { \
ArrayInit(tmp, init_val, dimy); \
ArrayInit(bar, tmp, dimx); \
}
int iTemp[];
char cTemp[];
//********************************************************************
char xStart, yStart, xDest, yDest;
const int MadlyEnormous=SHRT_MAX;
const char occ=1;
const char MapSize=46; // 45x45 fields
char SuperSize=MapSize+1;
const char Radius=MapSize/2;
char Map [][]; // besetzt=1 / frei=0;
char xPrev[][]; // Abszisse von Vorgaenger (x)
char yPrev[][]; // Ordinate von Vorgaenger (y)
char dPrev[][]; // Richtung zu Vorgaenger (d= 0-7)
int F[][]; // gesamte Wege-Kosten F
char List[][]; // gehoert zu Liste: undef=0 offen=1 geschlossen=2
//********************************************************************
char GetMap(char x, char y) // Zustand des Feldes: 0=frei, 1= Hindernis
{ return Map[x+Radius][y+Radius];}
void SetMap(char x, char y, char val)
{ Map[x+Radius][y+Radius]=val;}
char GetxPrev(char x, char y) // gespeicherter Vorgaenger: x-Koord.
{ return xPrev[x+Radius][y+Radius];}
void SetxPrev(char x, char y, char xPtr)
{ xPrev[x+Radius][y+Radius]=xPtr;}
char GetyPrev(char x, char y) // gespeicherter Vorgaenger: y-Koord.
{ return yPrev[x+Radius][y+Radius];}
void SetyPrev(char x, char y, char yPtr)
{ yPrev[x+Radius][y+Radius]=yPtr;}
char GetdPrev(char x, char y) // gespeicherter Vorgaenger: Richtung
{ return dPrev[x+Radius][y+Radius];}
void SetdPrev(char x, char y, char d)
{ dPrev[x+Radius][y+Radius]=d;}
int GetF(int x, int y) // Wege-Kosten F
{ return F[x+Radius][y+Radius];}
void SetF(int x, int y, int val)
{ F[x+Radius][y+Radius]=val;}
char GetList(char x, char y) // Listen-Zugehoerigkeit (0, 1, 2)
{ return List[x+Radius][y+Radius];}
void SetList(char x, char y, char val)
{ List[x+Radius][y+Radius]=val;}
//********************************************************************
//********************************************************************
void SetMapPixel(char x, char y) // Transformation der Koordinatensysteme:
// Nullpunkt= Mitte des Feldes!
{
PointOut(Radius+1+x, Radius+1+y, DRAW_OPT_NORMAL);
}
//********************************************************************
void ClearPixel (char x, char y)
{
PointOut(Radius+1+x, Radius+1+y, DRAW_OPT_CLEAR );
}
//********************************************************************
void ClearMapPixel(char x, char y) // Karten-Pixel loeschen
{
int xPix, yPix;
xPix=Radius+1+x;
yPix=Radius+1+y;
ClearPixel(xPix, yPix);
}
//********************************************************************
//********************************************************************
void SetMapAndPixel(char x, char y, char val )
{
SetMap(x, y, val);
SetMapPixel(x, y);
}
//********************************************************************
//********************************************************************
int GetNx(char x, char pos) // 3 2 1 benachbarte x-Koordinaten
{ // 4 0
int nx; // 5 6 7
nx=MadlyEnormous; // wenn ungueltiger Nachbar
if (((pos==1)||(pos==0)||(pos==7))&& (x<Radius-1))
{nx=x+1; }
else
if ((pos==2)||(pos==6))
{ nx=x; }
else
if (((pos==3)||(pos==4)||(pos==5))&&(x>(-Radius)))
{nx=x-1; }
return nx;
}
//********************************************************************
int GetNy(char y, char pos) // 3 2 1 benachbarte y-Koordinaten
{ // 4 0
int ny; // 5 6 7
ny=MadlyEnormous; // wenn ungueltiger Nachbar
if (((pos==1)||(pos==2)||(pos==3))&& (y<Radius-1))
{ ny=y+1; }
else
if ((pos==4)||(pos==0))
{ ny=y; }
else
if (((pos==5)||(pos==6)||(pos==7))&&(y>(-Radius)))
{ ny=y-1; }
return ny;
}
//********************************************************************
bool CloseToTheEdge(char x, char y, char dir) // 3 2 1 keine Hindernis-Kanten schneiden
{ // 4 0
bool edge; // 5 6 7
short xm,xp,ym,yp;
edge=false; // nur bei diagonalem Schritt beruecksichtigen!)
xm=(xm> -Radius ? x-1 : x);
xp=(xp< Radius-1 ? x+1 : x);
ym=(ym> -Radius ? y-1 : y);
yp=(yp< Radius-1 ? y+1 : y);
if (dir==1) {edge=((GetMap(xp,y)==occ)||(GetMap(x,yp)==occ));} // 0 2
else
if (dir==3) {edge=((GetMap(x,yp)==occ)||(GetMap(xm,y)==occ));} // 2 4
else
if (dir==5) {edge=((GetMap(xm,y)==occ)||(GetMap(x,ym)==occ));} // 4 6
else
if (dir==7) {edge=((GetMap(x,ym)==occ)||(GetMap(xp,y)==occ));} // 6 0
return edge;
}
//********************************************************************
void ExpandNode(char xa, char ya) // checkt Nachbarfelder von (xa, ya)
{
short F, d, k, v, w, z;
for (d=0;d<=7;d++)
{
v=GetNx(xa,d); // Nachbarn durchgehen: 3 2 1
w=GetNy(ya,d); // 4 0
// 5 6 7
if ((d==0) ||(d==2) ||(d==4) ||(d==6)) // ((p%2)==0 arbeitet fehlerhaft!)
{k=10; } // Kosten gerader Schritt: 10
else
{
k=14; // Kosten diagonaler Schritt: 15
if(CloseToTheEdge(xa,ya,d)) continue; // diagonal ist bei Hinderniskante verboten
}
if ((v<MadlyEnormous)&&(w<MadlyEnormous)) // gueltiger Nachbar ?!
{
z=GetMap(v,w); // Hindernis vorhanden?
if ( (z==0)&&(!(GetList(v,w)==2))) // frei und nicht in geschlossener Liste
{
F=GetF(xa,ya)+k; // F: Kosten zu (v,w) ueber aktuelles Quadrat (xa,ya)
if (!(GetList(v,w)==1)) // wenn NICHT in offener Liste
{
SetList (v,w,1); // dann in die offene uebernehmen
SetxPrev(v,w, xa); // Vorgaenger: ^x-aktuell
SetyPrev(v,w, ya); // Vorgaenger: ^y-aktuell
SetdPrev(v,w, d); // Richtung zum Vorgaenger (0-7)
if(d==GetdPrev(xa,ya)) F-=2; // Kosten geringer, wenn keine Kursaenderung
SetF(v,w,F); // Kosten gesamt
} // if (Nicht offen)
else
if (GetList(v,w)==1) // wenn aber bereits in offener Liste
{
if (F<=GetF(v,w)) // Wegekosten G dorthin vergleichen:
// neuer Weg dahin: geringere Kosten als alte Wegekosten ?
{ // dann ueberschreiben + neuen Weg im Quadrat einspeichern
SetxPrev(v,w, xa); // Vorgaenger: ^x-aktuell
SetyPrev(v,w, ya); // Vorgaenger: ^y-aktuell
SetdPrev(v,w, d); // Richtung zum Vorgaenger (0-7)
if(d==GetdPrev(xa,ya)) F-=2;// Kosten geringer, wenn keine Kursaenderung
SetF(v,w,F); // Kosten gesamt
}// if (neuer Weg besser)
} // else if (schon offen)
}// if (nicht besetzt, nicht geschlossen)
} // if (gueltiger Nachbar)
}// for
}//ExpandNode
//********************************************************************
//********************************************************************
void A_Stern (char xStart, char yStart, char xDest, char yDest)
{
int i, j, c=0;
char xAkt, yAkt, xOld, yOld, xd, yd, xDa, yDa;
int FMin=MadlyEnormous;
xAkt=xDest; // wir starten rueckwaerts und beginnen die Suche beim Ziel !
yAkt=yDest; // Das Quadrat, von dem aus gesucht wird, heisst "aktuelles Quadrat"
SetList(xAkt, yAkt, 1); // akt. Quadrat in Offene Liste (=1)
SetF (xAkt,yAkt,0); // Kosten F=G+H; G=0, H=0;
SetList(xAkt, yAkt, 2); // aktuelles Quadrat in geschlossene Liste uebernehmen
xd=abs(xDest-xStart);
yd=abs(yDest-yStart);
TextOut( 0,48, "paths= "); // Anzeige der Zahl der Zyklen/Wege
NumOut (50,48, c);
int istart, isign, jstart, jsign;
if (xDest>=xStart)
{istart=-Radius; isign= 1;}
else {istart=Radius-1; isign=-1;}
if (yDest>=yStart)
{jstart=-Radius; jsign= 1;}
else {jstart=Radius-1; jsign=-1;}
// solange das andere Ende (der Start) nicht gefunden wurde:
while (GetList(xStart,yStart)!=2)
{
FMin=MadlyEnormous;
xOld=xAkt;
yOld=yAkt;
// suche in offener Liste (=1)das Feld mit kleinstem F
for (i=istart; isign*i<Radius;i+=isign)
{
for (j=jstart; jsign*j<Radius;j+=jsign)
{
if ((GetList(i,j)==1)&&(GetF(i,j)<FMin) )
{
FMin=GetF(i,j);
xAkt=i; // wenn gefunden: nimm es als aktuelles Quadrat
yAkt=j;
xDa=abs(i-xStart);
yDa=abs(j-yStart);
if ((xDa<xd)||(yDa<yd))
{
SetList(xAkt, yAkt, 2); // aktuelles Quadrat in geschlossene Liste
SetMapPixel(xAkt,yAkt);
ExpandNode(xAkt, yAkt); // Nachbarfelder untersuchen
c+=1;
}
} // if
} // for j
SetList(xAkt, yAkt, 2); // aktuelles Quadrat in geschlossene Liste
SetMapPixel(xAkt,yAkt);
ExpandNode(xAkt, yAkt); // Nachbarfelder untersuchen
c+=1;
} // for i
TextOut(0,56, "Akt(X,Y)");
NumOut(50,56,xAkt);
NumOut(80,56,yAkt);
TextOut( 0,48, "paths= "); // Anzeige der Zahl der Zyklen/Wege
NumOut (50,48, c);
if((xAkt==xOld)&&(yAkt==yOld)&&(FMin==MadlyEnormous))
{
TextOut(0,48, "No Way!"); // Ziel ist unerreichbar!
PlayTone(220,100); Wait(250); //PlaySound(soundBeepBeep);
PlayTone(220,100); Wait(250);
Wait(2000);
break;
}
} // while
TextOut(50,10, "fertig", 0); // Anzeige, wenn fertig
ClearPixel(xStart,yStart);
Wait(2000);
}
//********************************************************************
//********************************************************************
void DrawMap() // Hindernisse und Start/Ziel zeichnen
{
char x, y;
RectOut( 1, 1, MapSize+1, MapSize+1);
//==========================================================================
x=8; // Hindernis setzen:
for (y=-3;y<=5;y++) // Hier kann man sich austoben und beliebige
{ // Hindernis-Punkte definieren:
SetMapAndPixel(x,y,occ);
}
y=9;
for (x=-8;x<=7;x++) // nochmal weitere
{ // Hindernis-Punkte definieren:
SetMapAndPixel(x,y,occ);
}
x=-8;
for (y=9;y>-10; y--)
{
SetMapAndPixel(x,y,occ);
}
y=-5;
for (x=0;x<=5;x++) // nochmal weitere
{ // Hindernis-Punkte definieren:
SetMapAndPixel(x,y,occ);
}
y=1;
for (x=10;x<=12;x++) // nochmal weitere
{ // Hindernis-Punkte definieren:
SetMapAndPixel(x,y,occ);
}
y=6;
for (x=8;x<=14;x++) // nochmal weitere
{ // Hindernis-Punkte definieren:
SetMapAndPixel(x,y,occ);
}
//....................................................................
SetMapPixel(xStart,yStart); // Start als Punkt malen
CircleOut(xDest+Radius+1, yDest+Radius+1, 1); // Ziel dick markieren
}
//********************************************************************
//********************************************************************
void WalkThisWay() // virtuelle Fahrt der berechneten Route
{
char x, y, xn, yn;
int dir, olddir, turn;
x=xStart;
y=yStart;
dir=0;
olddir=0;
turn=0;
TextOut( 0,56,"Turn= "); NumOut(50,56,turn);
TextOut( 0,48,"Hding= "); NumOut(50,48,dir);
TextOut(60,24,"Pos XY ");
TextOut(60,18," ");
NumOut (60,16,x); NumOut(80,16,y);
Wait(1000);
while (! ((x==xDest)&&(y==yDest)))
{
TextOut(60,24,"Pos XY ");
TextOut(60,18," ");
NumOut (60,16,x); NumOut(80,16,y);
SetMapPixel(x, y);
Wait(500);
dir=180+(45*GetdPrev(x,y));
if (dir>=360) dir-=360;
turn=dir-olddir;
if (turn<-180) turn=turn+360;
if (turn>180) turn=360-turn;
TextOut(0,56,"Turn= "); NumOut(50,56,turn);
Wait(200);
TextOut( 0,48,"Hding= "); NumOut(50,48,dir);
Wait(400);
olddir=dir;
xn=GetxPrev(x,y);
yn=GetyPrev(x,y);
x=xn;
y=yn;
}
SetMapPixel(x, y);
TextOut(60,24,"Pos XY ");
TextOut(60,18," ");
NumOut (60,16,x); NumOut(80,16,y);
TextOut(50,8,"Ziel");
TextOut(50,0,"erreicht!");
Wait(1000);
}
//********************************************************************
void initVar()
{
ArrayInit2D(F, iTemp, MadlyEnormous, MapSize, MapSize);
ArrayInit(iTemp,0,0); // free mem
ArrayInit2D(Map, cTemp, 0, SuperSize, SuperSize);
ArrayInit2D(xPrev, cTemp, 0, SuperSize, SuperSize);
ArrayInit2D(yPrev, cTemp, 0, SuperSize, SuperSize);
ArrayInit2D(dPrev, cTemp, 0, SuperSize, SuperSize);
ArrayInit2D(List , cTemp, 0, MapSize, MapSize);
ArrayInit(cTemp,0,0);
// try out different Start/Destination combinations
xStart=-15; yStart= 2; // Startpunkt definieren
xDest =13; yDest = 4; // Zielpunkt definieren
}
//********************************************************************
long time0, runtime;
task main()
{
time0=CurrentTick();
ClearScreen();
initVar();
DrawMap();
A_Stern(xStart,yStart,xDest, yDest);
runtime=CurrentTick()-time0;
ClearScreen();
TextOut(0,56, "runtime");
NumOut(0,48, runtime);
while (!ButtonPressed(BTNCENTER, false));
while(true)
{
ClearScreen();
DrawMap();
WalkThisWay();
Wait(2000);
}
}
//********************************************************************
//********************************************************************
//fw 20110702 Opt Lev 0: file error -1
//fw 20110702 Opt Lev 1: 221471
//fw 20110702 Opt Lev 2: 154688
//fw 20110702 Opt Lev 3: 154702
//fw 20110702 Opt Lev 4: 155658
//fw 20110719 Opt Lev 1: 216,025
//fw 20110719 Opt Lev 2: 151,912
//fw 20110719 Opt Lev 3: file error -1
//fw 20110719 Opt Lev 4: file error -1
Last edited by HaWe on 21 Jul 2011, 08:24, edited 2 times in total.
Re: BricxCC/NBC test release 2011-07-19
The problem in the matrix test program appears to be a low level compiler bug. If you add
TextOut(0, LCD_LINE1, "please work");
to the code anywhere in task main then it runs fine with the latest compiler at opt level 3. The only difference between the generated code was an additional byte array variable in the dataspace and the 5 lines or so of code emitted by TextOut at the end of task main where I inserted that line.
The tamtam code helped me remove what was a very unsafe optimization from the stuff I had added at level 3. I will upload a new test release later today.
John Hansen
TextOut(0, LCD_LINE1, "please work");
to the code anywhere in task main then it runs fine with the latest compiler at opt level 3. The only difference between the generated code was an additional byte array variable in the dataspace and the 5 lines or so of code emitted by TextOut at the end of task main where I inserted that line.
The tamtam code helped me remove what was a very unsafe optimization from the stuff I had added at level 3. I will upload a new test release later today.
John Hansen
Multi-platform LEGO MINDSTORMS programming
http://bricxcc.sourceforge.net/
http://bricxcc.sourceforge.net/
Re: BricxCC/NBC test release 2011-07-19
JFYI and for checking also opt level 2 settings in the new release,
old release 20110702 is fine,
with new release 20110720 ,
only level 1 is fine,
but already at opt level 2 after finishing about 3/4 of total run : file error -1
old release 20110702 is fine,
with new release 20110720 ,
only level 1 is fine,
but already at opt level 2 after finishing about 3/4 of total run : file error -1
Code: Select all
/////////////////////////////////////////////////////////////////////////////
// TamTam.c
// Version 1.0.9 "Dijkstra"
// virtuelle Wegsuche auf dem Display
//***************************************************************************
// getestet mit Bricxcc 3.3.8.10 (enhanced fw)
//***************************************************************************
// der A* (A-Stern, a-star) - Algorithmus fuer den NXT
// zur Wegsuche und Navigation an Hindernissen vorbei
//***************************************************************************
// hier in der Variante nach Dijkstra
// (keine geschaetzten heuristischen Kosten H, also H=0 => F=G!
//
// 1.0.8 neues Array Handling (=> get/free mem)
// 1.0.4 am Schluss werden Routenanweisungen erstellt
// 1.0.1 erkennt, wenn kein Weg zum Ziel existiert
// 0.8.9 Suchrichtung optimiert: direkte Wege werden sehr schnell gefunden
// 0.3.8 Kurse optimiert: Kurs-Aenderungen verursachen hoehere Kosten
// 0.2.9 schneiden von Hindernis-Kanten wird vermieden
// (c) H. W.
/////////////////////////////////////////////////////////////////////////////
#define printf1( _x, _y, _format1, _value1) { \
string sval1 = FormatNum(_format1, _value1); \
TextOut(_x, _y, sval1); \
}
#define ArrayInit2D(bar, tmp, init_val, dimx, dimy) { \
ArrayInit(tmp, init_val, dimy); \
ArrayInit(bar, tmp, dimx); \
}
int iTemp[];
char cTemp[];
//********************************************************************
char xStart, yStart, xDest, yDest;
const int MadlyEnormous=SHRT_MAX;
const char occ=1;
const char MapSize=44; // m*m fields
const char HypSize= (MapSize+1);
const char Radius= (MapSize/2);
const char rRadius= MapSize-Radius;
char Map [][]; // besetzt / frei=0;
char xPrev[][]; // Abszisse von Vorgaenger (x)
char yPrev[][]; // Ordinate von Vorgaenger (y)
char dPrev[][]; // Richtung zu Vorgaenger (d= 0-7)
int F[][]; // gesamte Wege-Kosten F
char List[][]; // zu Liste: undef=0 offen=1 geschlossen=2
//********************************************************************
char GetMap(char x, char y) // Zustand des Feldes: 0=frei, 1= Hindernis
{ return Map[x+Radius][y+Radius];}
void SetMap(char x, char y, char val)
{ Map[x+Radius][y+Radius]=val;}
char GetxPrev(char x, char y) // gespeicherter Vorgaenger: x-Koord.
{ return xPrev[x+Radius][y+Radius];}
void SetxPrev(char x, char y, char xPtr)
{ xPrev[x+Radius][y+Radius]=xPtr;}
char GetyPrev(char x, char y) // gespeicherter Vorgaenger: y-Koord.
{ return yPrev[x+Radius][y+Radius];}
void SetyPrev(char x, char y, char yPtr)
{ yPrev[x+Radius][y+Radius]=yPtr;}
char GetdPrev(char x, char y) // gespeicherter Vorgaenger: Richtung
{ return dPrev[x+Radius][y+Radius];}
void SetdPrev(char x, char y, char d)
{ dPrev[x+Radius][y+Radius]=d;}
int GetF(int x, int y) // Wege-Kosten F
{ return F[x+Radius][y+Radius];}
void SetF(int x, int y, int val)
{ F[x+Radius][y+Radius]=val;}
char GetList(char x, char y) // Listen-Zugehoerigkeit (0, 1, 2)
{ return List[x+Radius][y+Radius];}
void SetList(char x, char y, char val)
{ List[x+Radius][y+Radius]=val;}
//********************************************************************
//********************************************************************
void SetMapPixel(char x, char y) // Transformation der Koordinatensysteme:
// Nullpunkt= Mitte des Feldes!
{
PointOut(Radius+x+1, Radius+y+1, DRAW_OPT_NORMAL);
}
//*****************
void ClearMapPixel(char x, char y) // Karten-Pixel loeschen
{
PointOut(Radius+1+x, Radius+1+y, DRAW_OPT_CLEAR );
}
//********************************************************************
void SetMapAndPixel(char x, char y, char val )
{
SetMap(x, y, val);
SetMapPixel(x, y);
}
//********************************************************************
//********************************************************************
int GetNx(char x, char pos) // 3 2 1 benachbarte x-Koordinaten
{ // 4 0
int nx; // 5 6 7
nx=MadlyEnormous; // wenn ungueltiger Nachbar
if (((pos==1)||(pos==0)||(pos==7))&& (x<Radius-1))
{nx=x+1; }
else
if ((pos==2)||(pos==6))
{ nx=x; }
else
if (((pos==3)||(pos==4)||(pos==5))&&(x>(-Radius)))
{nx=x-1; }
return nx;
}
//********************************************************************
int GetNy(char y, char pos) // 3 2 1 benachbarte y-Koordinaten
{ // 4 0
int ny; // 5 6 7
ny=MadlyEnormous; // wenn ungueltiger Nachbar
if (((pos==1)||(pos==2)||(pos==3))&& (y<Radius-1))
{ ny=y+1; }
else
if ((pos==4)||(pos==0))
{ ny=y; }
else
if (((pos==5)||(pos==6)||(pos==7))&&(y>(-Radius)))
{ ny=y-1; }
return ny;
}
//********************************************************************
bool CloseToTheEdge(char x, char y, char dir) // 3 2 1 keine Hindernis-Kanten schneiden
{ // 4 0
bool edge; // 5 6 7
short xm,xp,ym,yp;
edge=false; // nur bei diagonalem Schritt beruecksichtigen!)
xm=(xm> -Radius ? x-1 : x);
xp=(xp< Radius-1 ? x+1 : x);
ym=(ym> -Radius ? y-1 : y);
yp=(yp< Radius-1 ? y+1 : y);
if (dir==1) {edge=((GetMap(xp,y)==occ)||(GetMap(x,yp)==occ));} // 0 2
else
if (dir==3) {edge=((GetMap(x,yp)==occ)||(GetMap(xm,y)==occ));} // 2 4
else
if (dir==5) {edge=((GetMap(xm,y)==occ)||(GetMap(x,ym)==occ));} // 4 6
else
if (dir==7) {edge=((GetMap(x,ym)==occ)||(GetMap(xp,y)==occ));} // 6 0
return edge;
}
//********************************************************************
void ExpandNode(char xa, char ya) // checkt Nachbarfelder von (xa, ya)
{
short F, d, k, v, w, z;
for (d=0;d<=7;d++)
{
v=GetNx(xa,d); // Nachbarn durchgehen: 3 2 1
w=GetNy(ya,d); // 4 0
// 5 6 7
if ((d==0) ||(d==2) ||(d==4) ||(d==6)) // ((p%2)==0 arbeitet fehlerhaft!)
{k=10; } // Kosten gerader Schritt: 10
else
{
k=14; // Kosten diagonaler Schritt: 15
if(CloseToTheEdge(xa,ya,d)) continue; // diagonal ist bei Hinderniskante verboten
}
if ((v<MadlyEnormous)&&(w<MadlyEnormous)) // gueltiger Nachbar ?!
{
z=GetMap(v,w); // Hindernis vorhanden?
if ( (z==0)&&(!(GetList(v,w)==2))) // frei und nicht in geschlossener Liste
{
F=GetF(xa,ya)+k; // F: Kosten zu (v,w) ueber aktuelles Quadrat (xa,ya)
if (!(GetList(v,w)==1)) // wenn NICHT in offener Liste
{
SetList (v,w, 1); // dann in die offene uebernehmen
SetxPrev(v,w, xa); // Vorgaenger: ^x-aktuell
SetyPrev(v,w, ya); // Vorgaenger: ^y-aktuell
SetdPrev(v,w, d); // Richtung zum Vorgaenger (0-7)
if(d==GetdPrev(xa,ya)) F-=2; // Kosten geringer, wenn keine Kursaenderung
SetF(v,w,F); // Kosten gesamt
} // if (Nicht offen)
else
if (GetList(v,w)==1) // wenn aber bereits in offener Liste
{
if (F<=GetF(v,w)) // Wegekosten G dorthin vergleichen:
// neuer Weg dahin: geringere Kosten als alte Wegekosten ?
{ // dann ueberschreiben + neuen Weg im Quadrat einspeichern
SetxPrev(v,w, xa); // Vorgaenger: ^x-aktuell
SetyPrev(v,w, ya); // Vorgaenger: ^y-aktuell
SetdPrev(v,w, d); // Richtung zum Vorgaenger (0-7)
if(d==GetdPrev(xa,ya)) F-=2;// Kosten geringer, wenn keine Kursaenderung
SetF(v,w,F); // Kosten gesamt
} // if (neuer Weg besser)
} // else if (schon offen)
} // if (nicht besetzt, nicht geschlossen)
} // if (gueltiger Nachbar)
}// for
}//ExpandNode
//********************************************************************
//********************************************************************
void A_Stern (char xStart, char yStart, char xDest, char yDest)
{
int i, j, pc=0;
char xAkt, yAkt, xOld, yOld, xd, yd, xDa, yDa;
int FMin=MadlyEnormous;
xAkt=xDest; // wir starten rueckwaerts und beginnen die Suche beim Ziel !
yAkt=yDest; // Das Quadrat, von dem aus gesucht wird, heisst "aktuelles Quadrat"
SetList(xAkt, yAkt, 1); // akt. Quadrat in Offene Liste (=1)
SetF (xAkt, yAkt, 0); // Kosten F=G+H; G=0, H=0;
SetList(xAkt, yAkt, 2); // aktuelles Quadrat in geschlossene Liste uebernehmen
xd=abs(xDest-xStart);
yd=abs(yDest-yStart);
TextOut(56,56, "paths= ");
TextOut(56,40, "Akt X|Y");
printf1(56,48, "%6d", pc); // Anzeige der Zahl der Zyklen/Wege
int istart, isign, jstart, jsign;
if (xDest>=xStart)
{istart=-Radius; isign= 1;}
else {istart=rRadius-1; isign=-1;}
if (yDest>=yStart)
{jstart=-Radius; jsign= 1;}
else {jstart=rRadius-1; jsign=-1;}
// solange das andere Ende (der Start) nicht gefunden wurde:
while (GetList(xStart,yStart)!=2)
{
FMin=MadlyEnormous;
xOld=xAkt;
yOld=yAkt;
// suche in offener Liste (=1)das Feld mit kleinstem F
for (i=istart; isign*i<rRadius;i+=isign)
{
for (j=jstart; jsign*j<rRadius;j+=jsign)
{
if ((GetList(i,j)==1)&&(GetF(i,j)<FMin) )
{
FMin=GetF(i,j);
xAkt=i; // wenn gefunden: nimm es als aktuelles Quadrat
yAkt=j;
xDa=abs(i-xStart);
yDa=abs(j-yStart);
if ((xDa<xd)||(yDa<yd))
{
SetList(xAkt, yAkt, 2); // aktuelles Quadrat in geschlossene Liste
SetMapPixel(xAkt,yAkt);
ExpandNode(xAkt, yAkt); // Nachbarfelder untersuchen
pc+=1;
}
} // if
} // for j
SetList(xAkt, yAkt, 2); // aktuelles Quadrat in geschlossene Liste
SetMapPixel(xAkt,yAkt);
ExpandNode(xAkt, yAkt); // Nachbarfelder untersuchen
pc+=1;
} // for i
printf1(56,48, "%6d", pc); // Anzeige der Zahl der Zyklen/Wege
printf1(56,32, "%3d", xAkt); // x, y Position akt. Feld
printf1(80,32, "%3d", yAkt);
if((xAkt==xOld)&&(yAkt==yOld)&&(FMin==MadlyEnormous))
{
TextOut(56,08, "No Way!"); // Ziel ist unerreichbar!
PlayTone(220,100); Wait(250); //PlaySound(soundBeepBeep);
PlayTone(220,100); Wait(250);
Wait(2000);
break;
}
} // while
TextOut(56,08, "fertig", 0); // Anzeige, wenn fertig
ClearMapPixel(xStart,yStart);
Wait(2000);
}
//********************************************************************
//********************************************************************
void DrawMap() // Hindernisse und Start/Ziel zeichnen
{
char x, y;
RectOut( 0, 0, MapSize+1, MapSize+1);
//==========================================================================
x=0; // Hindernis setzen:
for (y=5;y<=rRadius-1;++y) // Hier kann man sich austoben und beliebige
{ // Hindernis-Punkte definieren
SetMapAndPixel(x,y,occ);
}
x=-8;
for (y=-5;y<=5;++y)
{ // Hindernis-Mauer definieren
SetMapAndPixel(x,y,occ);
}
x=8;
for (y=-15;y<=12;++y)
{ // Hindernis-Mauer definieren
SetMapAndPixel(x,y,occ);
}
y=12;
for (x=8;x<=rRadius-5;++x)
{ // Hindernis-Mauer definieren:
SetMapAndPixel(x,y,occ);
}
y=-8;
for (x=8;x<=rRadius-5;++x)
{ // Hindernis-Mauer definieren:
SetMapAndPixel(x,y,occ);
}
//....................................................................
SetMapPixel(xStart,yStart); // Start als Punkt
SetMapPixel(xDest, yDest); // Destination als Punkt
}
//********************************************************************
//********************************************************************
void WalkThisWay() // virtuelle Fahrt der berechneten Route
{
char x, y, xn, yn;
int dir, olddir, turn;
x=xStart;
y=yStart;
dir=0;
olddir=0;
turn=0;
TextOut(56,56,"Turn=");
TextOut(56,40,"Hding=");
TextOut(56,24,"Pos XY ");
printf1(56,48,"%4d", turn);
printf1(56,32,"%4d", dir);
printf1(56,16,"%3d", x); printf1 (80,16,"%3d",y);
Wait(1000);
while (! ((x==xDest)&&(y==yDest)))
{
printf1(56,16,"%3d", x); printf1(80,16,"%3d",y);
SetMapPixel(x, y);
Wait(500);
dir=180+(45*GetdPrev(x,y));
if (dir>=360) dir-=360;
turn=dir-olddir;
if (turn<-180) turn=turn+360;
if (turn>180) turn=360-turn;
printf1(56,48,"%4d", turn);
Wait(200);
printf1 (56,32,"%4d", dir);
Wait(400);
olddir=dir;
xn=GetxPrev(x,y);
yn=GetyPrev(x,y);
x=xn;
y=yn;
}
SetMapPixel(x, y);
printf1(56,16,"%3d", x); printf1(80,16,"%3d",y);
TextOut(50,8," Ziel");
TextOut(50,0,"erreicht");
Wait(1000);
}
//********************************************************************
void initVar()
{
ArrayInit2D(F, iTemp, MadlyEnormous, HypSize, HypSize);
ArrayInit(iTemp,0,0); // free temp mem
ArrayInit2D(Map, cTemp, 0, HypSize, HypSize);
ArrayInit2D(xPrev, cTemp, 0, HypSize, HypSize);
ArrayInit2D(yPrev, cTemp, 0, HypSize, HypSize);
ArrayInit2D(dPrev, cTemp, 0, HypSize, HypSize);
ArrayInit2D(List , cTemp, 0, HypSize, HypSize);
ArrayInit(cTemp,0,0); // free temp mem
// try out different Start/Dest
// Start definieren
xStart= -12;
yStart= -2;
// Dest definieren
xDest = MapSize-Radius-1;
yDest = 5;
}
//********************************************************************
task main()
{
ClearScreen();
initVar();
DrawMap();
A_Stern(xStart,yStart,xDest, yDest);
while(true)
{
ClearScreen();
DrawMap();
WalkThisWay();
Wait(2000);
}
}
//********************************************************************
//********************************************************************
Last edited by HaWe on 21 Jul 2011, 09:12, edited 1 time in total.
Re: BricxCC/NBC test release 2011-07-19
JFYI, by "help testing" I really had something more in mind than "try it and complain when it doesn't work and post large programs that fail in previous versions". Your 1.0.9 version of tamtam works fine at level 3 optimization (after my fix from yesterday). It still crashes when it is nearly finished at level 2 optimizations. Do you have any theories as to how code optimizations could affect your program in a way that only shows up after the same code has been executed thousands of times?
I have replaced the previous test release zip with one uploaded this morning and dated 2011-07-20. It has a fix for the level 3 optimization bug mentioned yesterday plus support for the CruizCore XG1300L sensor and a fix for the I2CVendorId, I2CVersion, and I2CDeviceId API functions which had been truncating data at 7 bytes instead of returning the full 8 bytes.
Please notice how all 4 of these new API "functions" are defined as #define macros in NXCDefs.h so they cannot accept NXC expressions for any of their parameters. They may be changed to inline functions at some point in the future.
John Hansen
I have replaced the previous test release zip with one uploaded this morning and dated 2011-07-20. It has a fix for the level 3 optimization bug mentioned yesterday plus support for the CruizCore XG1300L sensor and a fix for the I2CVendorId, I2CVersion, and I2CDeviceId API functions which had been truncating data at 7 bytes instead of returning the full 8 bytes.
Code: Select all
struct XGPacketType {
int AccAngle;
int TurnRate;
int XAxis;
int YAxis;
int ZAxis;
};
#define ResetMIXG1300L(_port) asm { __ResetMIXG1300L(_port, __RETVAL__) }
#define SensorMIXG1300LScale(_port) asm { __ReadSensorMIXG1300LScale(_port, __RETVAL__) }
#define SetSensorMIXG1300LScale(_port, _scale) asm { __SetSensorMIXG1300LScale(_port, _scale, __RETVAL__) }
#define ReadSensorMIXG1300L(_port, _packet) asm { \
compchktype _packet, XGPacketType \
__ReadSensorMIXG1300L(_port, _packet, __RETVAL__) \
}
John Hansen
Multi-platform LEGO MINDSTORMS programming
http://bricxcc.sourceforge.net/
http://bricxcc.sourceforge.net/
Re: BricxCC/NBC test release 2011-07-19
no, sorry, I have no idea.
It always has been working fine with all previous versions on level 1.
(I was always only using level 1 until now for all my programs.)
Are you interested to get reports about large crashing programs on different optimization levels for your new releases or not?
It always has been working fine with all previous versions on level 1.
(I was always only using level 1 until now for all my programs.)
Are you interested to get reports about large crashing programs on different optimization levels for your new releases or not?
Re: BricxCC/NBC test release 2011-07-19
anyway, that's odd.
for tamtam 1.09 it says with release 20110720
level 0 file error -1
level 1 (runs ok)
level 2 (premature abort)
level 3 (runs ok)
So for level 1+3 the program calculates fine.
Now I add / insert a "stop watch"...:
Now:
level 0 file error -1
level 1 doesn't expand nodes correctly anymore (no "cloud", just a diagonal line), found "no way", 19569 msec
level 2 file error -2
level 3 doesn't expand nodes correctly anymore (no "cloud", just a diagonal line), "fertig"(finished) although expanded only 7 fields, 16249 msec
level 4 (same as 3)
Removing the stop watch, all is fine again for level 1+3 as before.
But it's also the same for older release versions. Reloading 20110702 it happens the same for stop watch, fine if no stop watch.
(Only if you are interested in this issue for optimizing NXC)
ps, I'm not complaining, I'm just reporting.
for tamtam 1.09 it says with release 20110720
level 0 file error -1
level 1 (runs ok)
level 2 (premature abort)
level 3 (runs ok)
So for level 1+3 the program calculates fine.
Now I add / insert a "stop watch"...:
Code: Select all
long starttime, runtime;
void showtime() {
runtime=CurrentTick()-starttime;
ClearScreen();
TextOut(0,56,"runtime");
NumOut(0,48,runtime);
while(!ButtonPressed(BTNCENTER,false));
while( ButtonPressed(BTNCENTER,false));
}
//********************************************************************
task main()
{
starttime=CurrentTick();
//...
showtime();
//...
level 0 file error -1
level 1 doesn't expand nodes correctly anymore (no "cloud", just a diagonal line), found "no way", 19569 msec
level 2 file error -2
level 3 doesn't expand nodes correctly anymore (no "cloud", just a diagonal line), "fertig"(finished) although expanded only 7 fields, 16249 msec
level 4 (same as 3)
Removing the stop watch, all is fine again for level 1+3 as before.
But it's also the same for older release versions. Reloading 20110702 it happens the same for stop watch, fine if no stop watch.
(Only if you are interested in this issue for optimizing NXC)
ps, I'm not complaining, I'm just reporting.
Last edited by HaWe on 21 Jul 2011, 09:08, edited 2 times in total.
Re: BricxCC/NBC test release 2011-07-19
I am interested in hearing reports about defects in NBC/NXC so that I can fix them but it is not terribly helpful to hand me a large program and a simple statement that it doesn't work right in certain situations. It is, however, helpful when you dig deeper, as you have now done, and find that adding or subtracting certain bits of code change the behavior. In this case, it appears to be that adding a structure to the dataspace (the structure used by the TextOut in showtime) is "doing something" that is messing around with how the VM executes the code somehow. It is not clear to me yet exactly what is going on but it is not an issue, per se, with the optimizations other than that code optimizations can cause the compiler to remove unused declarations from the dataspace. It is something buggy deep inside the compiler that happens to be revealed with just the right (or wrong) combination of variable declarations in the dataspace. In other words, you were simply lucky that your code worked at optimization level 1 with previous versions of NBC.
John Hansen
John Hansen
Multi-platform LEGO MINDSTORMS programming
http://bricxcc.sourceforge.net/
http://bricxcc.sourceforge.net/
Re: BricxCC/NBC test release 2011-07-19
ok, maybe it's really a program bug, not a compiler bug,
maybe depending on requested memory.
So a new test -
for tamtam109
new release 20110720,
reducing the array sizes from 44 to 40,
including stop watch:
level 0 file error -1
level 1 file error -5
level 2 expanding nodes: ok, 152407 msec, showing the route> ok
level 3 expanding nodes: ok, 152286 msec, showing the route> accidentally complete abort, NXT switches off, other times: ok
same code with old release 20110702
level 0 file error -1
level 1 ~220000 msec always ok
level 2 ~153000 msec always ok
level 3 ~152000 msec always ok .
so it's probably a new issue because of latest fw/compiler changes.
strange that :
level 0 ALWAYS gives file error -1 for every fw
level 1 file error -5 (new release ) is quite unexpected especially because required mem has been reduced
maybe depending on requested memory.
So a new test -
for tamtam109
new release 20110720,
reducing the array sizes from 44 to 40,
including stop watch:
level 0 file error -1
level 1 file error -5
level 2 expanding nodes: ok, 152407 msec, showing the route> ok
level 3 expanding nodes: ok, 152286 msec, showing the route> accidentally complete abort, NXT switches off, other times: ok
same code with old release 20110702
level 0 file error -1
level 1 ~220000 msec always ok
level 2 ~153000 msec always ok
level 3 ~152000 msec always ok .
so it's probably a new issue because of latest fw/compiler changes.
strange that :
level 0 ALWAYS gives file error -1 for every fw
level 1 file error -5 (new release ) is quite unexpected especially because required mem has been reduced
Last edited by HaWe on 21 Jul 2011, 09:08, edited 3 times in total.
Who is online
Users browsing this forum: No registered users and 1 guest