Eagle ULP: hulp bij blinde vlek nodig.

fatbeard

Honourable Member

Ik heb de volgende stukken ULP code uit een programma wat een library moet maken vanuit een schema.

code:

  P.wires(w)
  { if((w.x1==oldX)&&(w.y1==oldY))
    { if(strlen(wrk)-strrchr(wrk,'\n')>LineLengthLimit) wrk+="\\\n     ";
      if(w.arc) sprintf(wrk,"%s (%g %g) %g",wrk,u2mm(w.x2),u2mm(w.y2),w.curve);
      else sprintf(wrk,"%s (%g %g)",wrk,u2mm(w.x2),u2mm(w.y2));
    }
    else
    { sprintf(wrk,"%s(%g %g)",wrk,u2mm(w.x1),u2mm(w.y1));
      if(w.arc) sprintf(wrk,"%s %g (%g %+g)",wrk,w.curve,u2mm(w.x2),u2mm(w.y2));
      else sprintf(wrk,"%s (%g %g)",wrk,u2mm(w.x2),u2mm(w.y2));
    }
    oldX=w.x2;
    oldY=w.y2;
  }
  wrk+=";\n";

code:

        S.wires(w)
        { hasWires=TRUE;
          lineFull=FALSE;
          if(strlen(wrk)-strrchr(wrk,'\n') > LineLengthLimit) lineFull=TRUE;
          wrk+=makeWire(w,oldX,oldY);
          oldX=w.x2;
          oldY=w.y2;
        }
        if(hasWires) wrk+=";\n";

code:

string makeWire(UL_WIRE w,real oldX,real oldY)
{ string tmp;
  if((w.x1==oldX)&&(w.y1==oldY))
  { if(lineFull) tmp+="\\\n     ";
    if(w.arc) sprintf(tmp," (%g %g) %s%g",u2mm(w.x2),u2mm(w.y2),Pcap(w.arc.cap),w.curve);
    else sprintf(tmp," (%g %g)",u2mm(w.x2),u2mm(w.y2));
  }
  else
  { tmp+=checkLayer(w.layer);
    tmp+=checkStyle(w.style);
    sprintf(tmp,"%s\nwire %g (%g %g)",tmp,u2mm(w.width),u2mm(w.x1),u2mm(w.y1));
    if(w.arc) sprintf(tmp,"%s%s %g (%g %g)",tmp,Pcap(w.arc.cap),w.curve,u2mm(w.x2),u2mm(w.y2));
    else sprintf(tmp,"%s (%g %g)",tmp,u2mm(w.x2),u2mm(w.y2));
  }
  return tmp;
}

Het eerste stuk komt uit een routine die polygons maakt, het tweede deel uit een routine die symbolen maakt.
De variabele lineFull is globaal gedefinieerd, de rest is lokaal per routine.
LineLengthLimit is een globaal gedefinieerde 'constante' en heeft de waarde 80.

Nu werkt de 'volle regel afhandeling' wèl bij de polygonen maar niet bij de symbolen, ik zie alleen niet waarom. Het moet iets blatant eenvoudigs zijn, op het stomme af.
Okokok, de geproduceerde data is ook nog niet 100%, maar dat is het probleem niet.

Wie weet waar ik de plank mis sla?

Een goed begin is geen excuus voor half werk; goed gereedschap trouwens ook niet. Niets is ooit onmogelijk voor hen die het niet hoeven te doen.

Je "regel vol" afhandeling staat in 1 tak van een IF statement. Als ie steeds de ELSE induikt, dan ziet ie de regel-vol-afhandeling nooit.

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/
fatbeard

Honourable Member

In de polygon maker (1e brok code) staat die afhandeling ook in de 1e tak van eenzelfde IF statement en daar werkt-ie dus wel...

Polygon output:
polygon 0.1 (-57.7292 30.0293) (-55.4195 30.0293) (-55.4195 27.2342) (-53.7183 27.2342) \
(-53.7183 30.0299) (-52.5026 30.0299) (-52.5026 27.2342) (-49.099 27.2342) \
(-48.9648 27.2446) (-48.8985 27.2538) (-48.5112 27.4059) (-48.0837 27.7867) \
(-47.7747 28.2686) (-47.5319 28.9423) (-47.4314 29.4801) (-47.3977 30.0299) \
(-45.5747 30.0296) (-57.7292 30.0293) -179.997;

Wire output:
wire 0.0508 (-21.962 34.196) (-21.338 36.2864) (-19.154 36.2864) (-19.2632 35.9276) (-20.8388 35.9276) (-20.9792 35.4596) (-19.4504 35.4596) (-19.5596 35.1164) (-21.0728 35.1164) (-21.26 34.5392) (-19.544 34.5392) (-19.6532 34.196) (-21.962 34.196);

Een goed begin is geen excuus voor half werk; goed gereedschap trouwens ook niet. Niets is ooit onmogelijk voor hen die het niet hoeven te doen.
fatbeard

Honourable Member

|:( |:( |:(
Hij werkt wel, maar wordt meteen overschreven in de daaropvolgende sprintf's...
Ik wist wel dat het iets zeer stompzinnigs moest zijn...

Gecorrigeerd (zoek de verschillen ;) ) :

code:

string makeWire(UL_WIRE w,real oldX,real oldY)
{ string tmp;
  if((w.x1==oldX)&&(w.y1==oldY))
  { if(lineFull) tmp+="\\\n     ";
    if(w.arc) sprintf(tmp,"%s (%g %g) %s%g",tmp,u2mm(w.x2),u2mm(w.y2),Pcap(w.arc.cap),w.curve);
    else sprintf(tmp,"%s (%g %g)",tmp,u2mm(w.x2),u2mm(w.y2));
  }
  else
  { tmp+=checkLayer(w.layer);
    tmp+=checkStyle(w.style);
    sprintf(tmp,"%s\nwire %g (%g %g)",tmp,u2mm(w.width),u2mm(w.x1),u2mm(w.y1));
    if(w.arc) sprintf(tmp,"%s%s %g (%g %g)",tmp,Pcap(w.arc.cap),w.curve,u2mm(w.x2),u2mm(w.y2));
    else sprintf(tmp,"%s (%g %g)",tmp,u2mm(w.x2),u2mm(w.y2));
  }
  return tmp;
}
Een goed begin is geen excuus voor half werk; goed gereedschap trouwens ook niet. Niets is ooit onmogelijk voor hen die het niet hoeven te doen.

haha! Die had ik BIJNA gespot. Ik wilde nog een een opmerking maken over de rare manier waarop je iets aan een string toevoegde.

Het is een beetje "kantjeboord" om het zo te doen. Er wordt bij het afhandelen van de sprintf tegelijkertijd gelezen en geschreven naar dezelfde string. Omdat het schrijven nu precies naar de locatie gebeurt die net zojuist voor het laatst gelezen is, dan gaat dat goed. Dat zou in "rare" omstandigheden toch fout kunnen gaan. Stel dat ivm het verwerken van internationale tekens intern in 4-byte-karakters (of 2) gewerkt wordt. En dat de implementatie gewoon bij het lezen de boel vertaalt naar de expanded 4-byte chars. Dan de output string opbouwt en vervolgens in 1x weer compacteert tot 1-byte-chars, zonodig-meer. Nu wordt de output-string 4x (of 2x) sneller overschreven dan dat ie gelezen wordt. Oeps.

Ondanks dat het een regel meer code kost, zou ik overwegen om het anders te doen: sprintf naar een nieuwe string en dan strcat met de oude. Of (ik weet niet zeker of dat in ULP kan)

code:

sprintf (wrk+strlen(wrk), "....", ... );
four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/
fatbeard

Honourable Member

Dat gaat prima in ULP, maar dat kost dus meer tikwerk. En daar hou ik niet zo van (lijkt teveel op werk)... :P

De gekozen oplossing werkt hier probleemloos: een string is gewoon een verzameling bytes die intern niet expanderen.
Het gaat alleen fout als die string geïnterpreteerd moet worden door een schermfunctie: er wordt in deze versie van Eagle een beetje gehinkeld op twee benen met 'standaard C-like' en HTML output, wat van de layout soms een zooitje maakt...

Een goed begin is geen excuus voor half werk; goed gereedschap trouwens ook niet. Niets is ooit onmogelijk voor hen die het niet hoeven te doen.

@fatbeard, Ik had al een tijd naar jouw code zitten staren maar zag geen probleem.
Zelfs toen je aangaf dat het probleem in de sprintf zat duurde het nog even.

Op 14 december 2021 09:01:53 schreef rew:
Dat zou in "rare" omstandigheden toch fout kunnen gaan.

@rew, Ik vroeg me af hoe die bijzondere omstandigheid ook kon optreden in ULP. Ik neem eigenlijk aan dat daar gewoon 8 bits ascii wordt gebruikt, geen unicode of andere fratsen. Even een test gedraaid in ULP.
1 toevoegen aan een string gaat goed, dat heeft fatbeard ook al ondervonden.
2 andersom, het eerste deel van de string proberen te overschrijven, gebeurt niet, gaat ook goed.
3 voor het geval punt 2 door de optimiser wordt gecorrigeerd, aan 2 kanten iets er aan plakken, gaat ook goed.

code:

string tmp = "1234567890";
sprintf( tmp, "%s%s", tmp, "abcdefghi" );
dlgMessageBox( tmp);
tmp = "1234567890";
sprintf( tmp, "%s%s", "abcdefghi", tmp );
dlgMessageBox( tmp);
tmp = "1234567890";
sprintf( tmp, "%s%s%s", "abcdefghi", tmp, "abcdefghi" );
dlgMessageBox( tmp);
exit("");

dezelfde testjes uitgevoerd in C:

code:

char tmp[64];
strcpy( tmp, "1234567890" );
sprintf( tmp, "%s%s", tmp, "abcdefghi" );
cout << tmp << endl;
strcpy( tmp, "1234567890" );
sprintf( tmp, "%s%s", "abcdefghi", tmp );
cout << tmp << endl;
strcpy( tmp, "1234567890" );
sprintf( tmp, "%s%s%s", "abcdefghi", tmp, "abcdefghi" );
cout << tmp << endl;
return 0;

Output (warnings genegeerd):

code:

1234567890abcdefghi
abcdefghiabcdefghia
abcdefghiabcdefghiaabcdefghi

Daar hebben we een probleem gevonden, Zowel C als rew vinden dit niet fijn
C geeft een waarschuwing, in ULP houdt men er blijkbaar rekening mee dat men raar doet. :-)

reading can seriously damage your ignorance
fatbeard

Honourable Member

Tsja, het ís een raar taaltje... :P

Een goed begin is geen excuus voor half werk; goed gereedschap trouwens ook niet. Niets is ooit onmogelijk voor hen die het niet hoeven te doen.

Dat past toch goed bij ons!

reading can seriously damage your ignorance
fatbeard

Honourable Member

OK, volgende blinde vlek.
Misschien toch maar eens naar de oogarts gaan...

code:

void editScript()
{ dlgDialog("View/edit script")
  { dlgLabel("<center><font size=+2><b>Be sure to know what you are doing!");
    dlgHBoxLayout
    { dlgVBoxLayout dlgSpacing(900);    // fix vertical size
      dlgTextEdit(cmd);
    }
    dlgHBoxLayout dlgSpacing(700);      // fix horizontal size
    dlgHBoxLayout
    { dlgStretch(1);
      dlgPushButton("back") dlgAccept();
    }
  };
}

Ik krijg een syntax error op de regel
dlgTextEdit(cmd);

en kan niet vinden/bedenken waarom...

Saillant detail: dit brokje code is geknipt/-plakt uit een werkend stuk.

Een goed begin is geen excuus voor half werk; goed gereedschap trouwens ook niet. Niets is ooit onmogelijk voor hen die het niet hoeven te doen.

Is de syntax niet:

code:


dlgVBoxLayout { dlgSpacing(900); }

Bij veel statements laat je de accolades weg zoals if en while,
maar ULP is geen C, zou het eens proberen.

reading can seriously damage your ignorance

Edit:

Ik krijg een syntax error op de regel
{ dlgVBoxLayout dlgSpacing(900); // fix vertical size
en kan niet vinden/bedenken waarom...

je hebt de vraag veranderd
Blijkbaar was ik te snel :-)

[Bericht gewijzigd door hennep op dinsdag 21 december 2021 11:41:14 (65%)

reading can seriously damage your ignorance
fatbeard

Honourable Member

Oops, verkeerde regel genoemd, aangepast: dlgTextEdit(cmd); is de boosdoener.

Achter dlgVBoxLayout komt een statement (wat een blok kan/mag zijn).
Achter dlgDialog() moet een blok staan.

Een goed begin is geen excuus voor half werk; goed gereedschap trouwens ook niet. Niets is ooit onmogelijk voor hen die het niet hoeven te doen.
fatbeard

Honourable Member

8)7 als de foutmelding 'unknown identifier' was geweest had het meteen opgelost geweest: cmd was lokaal in het oude stuk en hier onbekend... |:( |:(

Hoebedoelu, verkeerde been?

Een goed begin is geen excuus voor half werk; goed gereedschap trouwens ook niet. Niets is ooit onmogelijk voor hen die het niet hoeven te doen.

Voor een oude compiler/interpreter.... worden variabele namen aan het "woordenboek" toegevoegd. Dus something (unknownstring) is dan een syntaxerror, want er moet of een getal of een variabele staan.

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/
fatbeard

Honourable Member

Maar als je ergens zegt:   Smurf+=1;     terwijl de declaratie luidt   int smurf;     zegt-ie wel "unknown identifier"...
Tikkie inconsistent als je het mij vraagt.

Dit alles terzijde: hier is versie 1.00, ter leeringh ende vermaeck.

Een goed begin is geen excuus voor half werk; goed gereedschap trouwens ook niet. Niets is ooit onmogelijk voor hen die het niet hoeven te doen.

Geen licentie, gemiste kans!
EDIT: Een hebberige nederlander heeft daar "een krat" bij geschreven. De originele versie in het engels

Als ik de ULP opstart (voorzichtig met: show/edit) dan krijg ik de tekst te zien: "Be sure to know what you are doing".
Dat weet ik dus niet. Enige uitleg is welkom.
De ULP start trouwens probleemloos in Eagle 7.7. Verder dan dat ben ik nog niet gekomen.

EDIT2:
In de tekst die wordt getoond onder show/edit vind ik: "grid mm;" terwijl ik toch echt inches heb ingesteld bij zowel board als schematic.

reading can seriously damage your ignorance
fatbeard

Honourable Member

Ach, misschien verander ik de licentie wel voor versie 1.2...

De tekst "be sure to know what you are doing" slaat op het mogelijk editen van het getoonde script (een foutje is zo gemaakt), de edit functie is bedoeld om te kunnen fijnslijpen.
Als je nix wijzigt is er nix aan de hand. Of je klikt HELP...

Het getoonde script zal, indien uitgevoerd, een of meerdere bibliotheken aanmaken in de projectdirectory.

De eenheid die je hebt ingesteld is alleen voor de grafische omgeving van de editors, intern werkt Eagle met een grid van 0.1 micron. Om daar optimaal gebruik van te kunnen maken moet het grid voor de te produceren bibliotheken op mm worden gezet.
De gereproduceerde symbolen en packages zouden dan exact dezelfde maten moeten hebben als de originelen.

Alle data (zowel het script en de bibliotheken) wordt opgeslagen in de project ditectory, als je daar geen bibliotheken hebt staan kun je het script gewoon starten.
N.B. Als je 'run' gebruikt wordt het script niet opgeslagen maar alleen uitgevoerd.

Een goed begin is geen excuus voor half werk; goed gereedschap trouwens ook niet. Niets is ooit onmogelijk voor hen die het niet hoeven te doen.

Ik heb een schema getekend met een enkele opamp er op.
MCP604P uit linear.lbr

Bij het uitvoeren van het script krijg ik een aantal errors:

Unknown gate/pin: +IN
Unknown gate/pin: -IN
Unknown gate/pin: OUT

Ik heb de indruk dat voor iedere component in de library deze 3 meldingen worden getoond.

Ligt dit aan v.7.7 of kun jij het reproduceren en is er mogelijk iets mis met die library van Linear?

EDIT:
Een schema met alleen een 0805 weerstand gaat goed, geen meldingen.
Ik heb ook de checkbox "skip unused..." getest en dat werk ook goed in 7.7.

reading can seriously damage your ignorance
fatbeard

Honourable Member

Ligt dit aan v.7.7 of kun jij het reproduceren en is er mogelijk iets mis met die library van Linear?

Geen van beide: is een bug.
Probleem ontstaat zodra er meerdere symbolen in een device zitten: daar heb ik dus ff geen rekening mee gehouden bij het connecten... |:(
Wordt opgelost in versie 1.10, maar dat zal alleen wel na de kerst zijn.

Ander bug(je): packages die alleen op de PCB staan (en dus geen device hebben, zoals targets en logo's) worden niet correct geëxporteerd: ze krijgen de orientatie en locatie die op de PCB is gebruikt. Is opgelost.

<edit>
Het bleek eenvoudiger in te passen dan ik dacht, hier is versie 1.10.
Doet alleen nog steeds geen update met de 'nieuwe'bibliotheken.

[Bericht gewijzigd door fatbeard op donderdag 23 december 2021 00:10:10 (12%)

Een goed begin is geen excuus voor half werk; goed gereedschap trouwens ook niet. Niets is ooit onmogelijk voor hen die het niet hoeven te doen.

Op 22 december 2021 22:30:26 schreef fatbeard:
Doet alleen nog steeds geen update met de 'nieuwe'bibliotheken.

Is dat belangrijk, je kunt toch de hele library opnieuw genereren.
Of zijn er beren op de weg die ik over het hoofd zie?

reading can seriously damage your ignorance
fatbeard

Honourable Member

Geen beren op de weg, alleen wat giftige slangen onder het gras... :P

Het einddoel is het schema/board geheel onafhankelijk maken van de geïnstalleerde bibliotheken door alle gebruikte parts en packages te extraheren en in (een) nieuwe bibliothe(e)k(en) onder te brengen.
Tijdens dat proces kunnen die parts ook worden ontdaan van alle 'ballast' (niet gebruikte packages).

Door nu het schema/board te updaten naar die nieuwe bibliothe(e)k(en) zodat de parts en packages terugverwijzen naar die nieuwe bibliothe(e)k(en) verdwijnen die ongebruikte packages ook uit het schema/board en heeft een wijziging/uitbreiding van een originele bibliotheek geen onverweachte bijwerkingen mocht het schema worden aangepast.
Dat scheelt soms een gigantische hoeveelheid ruimte, met de bijbehorende snelheidswinst (mijn PCs zijn niet zo snel).
Als neveneffect (buiten de vergrote kennis van de interne structuur) laat zich een en ander makkelijker converteren naar andere pakketten (in versie 5 zijn alle files binair)...

Een goed begin is geen excuus voor half werk; goed gereedschap trouwens ook niet. Niets is ooit onmogelijk voor hen die het niet hoeven te doen.

Ik heb, in het verleden, al een aantal keren een Eagle schema naar iemand gestuurd en daarna een bericht terug gekregen met de melding er ontbreekt een component/library. Dit is voor mij dus een handig tooltje om dat te voorkomen in de toekomst.
Ik had al opgemerkt dat wanneer een library is opgeslagen in de projectdirectory en ik een tweede keer het script draai, dat er dan veel meldingen worden getoond:
Pin name '?' already exists!
Het weggooien van de oude library volstaat dan voor mij maar misschien was het handiger geweest om de vraag te stellen: "update or overwrite library?".
Een update heeft dan weer als nadeel dat een component die je al uit het schema hebt verwijderd, ongebruikt achter blijft in de library.

reading can seriously damage your ignorance
fatbeard

Honourable Member

maar misschien was het handiger geweest om de vraag te stellen: "update or overwrite library?"

... en precies dat staat in het lijstje "wanted" ... ;)
Gaat zeker komen, zeer zeker in versie 2.0, misschien eerder.
Grote drukte op de zaak en heel slecht slapen zorgen voor wat vertraging.

Ben nu nog ff bezig met 1.20 (de update functie), zou volgende week klaar moeten zijn.

Een goed begin is geen excuus voor half werk; goed gereedschap trouwens ook niet. Niets is ooit onmogelijk voor hen die het niet hoeven te doen.
fatbeard

Honourable Member

't hééft even geduurd, maar hier is dan versie 1.20.

Redlijk tot volledig vrij van bugs, alleen de afhandeling van reeds bestaande libraries ontbreekt nog.

Een goed begin is geen excuus voor half werk; goed gereedschap trouwens ook niet. Niets is ooit onmogelijk voor hen die het niet hoeven te doen.