Firmware Tips Folge: 1 präzises Timing
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Hi
Der Timer 'os_timer' löst nur bis 1 ms auf
Hier mal ein insider Tip zum ausprobieren.
Damit kann man die Auflösung bis zur clock ( 12.5ns ) verwenden.
1
static inline unsigned get_ccount(void)
2
{
3
unsigned r;
4
asm volatile ("rsr %0, ccount" : "=r"(r));
5
return r;
6
}
Bei 80 MHz clock wird das Spezial Register 'CCOUNT' inkrementiert, und
zwar geschieht das alle 12.5ns ( 80 MHz ) bei jedem clock tick.
Hier einmal mein Beispiel Code:
1
..
2
static inline unsigned get_ccount(void);
3
..
4
5
6
7
static inline unsigned get_ccount(void)
8
{
9
unsigned r;
10
asm volatile ("rsr %0, ccount" : "=r"(r));
11
return r;
12
}
13
14
15
16
void user_init(void)
17
18
{
19
20
while(1)
21
22
{
23
24
char ticks1 [32];
25
char ticks2 [32];
26
27
unsigned tick1;
28
unsigned tick2;
29
unsigned tickdiff;
30
31
32
tick1 = get_ccount(); // Spezial Register CCOUNT Abruf und Übertrag
33
tick2 = get_ccount(); // Spezial Register CCOUNT Abruf und Übertrag
os_delay_us(10 *1000*1000); // Pause : Ablesen der Werte am LCD
53
54
lcdCmd(ClearDisplay); // LCD Command für Clear Display ausführen
55
56
57
} // while
58
} // user_init
Der Wert von 1 sagt aus, dass zwischen den beiden Abfragen 12.5ns
vergangen sind.
Ein weiterer Ansatz wäre aus der API,
1
uint32 system_get_time(void);
Damit kann man dann relative Zeitwerte abrufen z.b. vergangene Zeit
zwischen zwei interrupts oder auch andere.
Der Nachteil:
Die Auflösung ist im API Ansatz nur in us
Daher denke ich mal, dass der INLINE ASM code gut zu gebrauchen ist.
Viel Spas damit.
..
lg
rudi ;-)
Mal genauer betrachtet:
1 Mikrosekunden [µs] = 1 000 Nanosekunden [ns]
http://www.einheiten-umrechnen.de/einheiten-rechner.php?typ=zeit
Bild 1
mit einem delay 1µs zwischen den beiden Abrufen ergeben sich 122 ticks
122 ticks zu je 12.5 ns = 1525 µs
./. + 525 µs
Bild 2
mit einem delay 2µs zwischend den beiden Abrufen ergeben sich 194 ticks
144 ticks zu je 12.5 ns = 1800 µs
./. - 200 µs
Bild3
mit 2x je einem delay 1µs zwischend den beiden Abrufen ergeben sich 243
ticks
243 ticks zu je 12.5 ns = 3037,5 µs
./. + 1037.5 µs
lg
rudi ;-)
Mal ein Testergebnis mit einer while (mtick < 100 )
dabei wird vor der while schleife das CCOUNT abgerufen und der Wert
gespeichert, dann wird die while schleife 100 mal den abruf des
Registers CCOUNT immer wieder in die zweite Variable speichern.
Jetzt werden die Ticks ausgerechnet die dafür gebraucht wurden
spannendes Ergebnis:
1
..
2
int mtick = 0 ; // counter variable
3
..
4
..
5
6
// start
7
tick1 = get_ccount(); // Spezial Register CCOUNT Abruf und Übertrag
8
while (mtick < 100 )
9
{
10
tick2 = get_ccount(); // Spezial Register CCOUNT Abruf und Übertrag
dann die formation mit kontroll counter variable
1. zeile
erster Ticks abruf bei start || counter (100 aufrufe )
1
os_sprintf(ticks1, "%lu %i", tick1, mtick);
dann die formation mit erechneter worktime
2. zeile
letzter Ticks abruf (100) nach dem start || tickdiff
1
2
os_sprintf(ticks2, "%lu %lu", tick2, tickdiff);
wie gesagt,
ich hab neben dem OLED am SPI auch ein MCP23S17 über SPI am ESP8266
und betreibe ein einfaches 16 Zeichen x 2 Display daran
daher ganz simple LCD Ausgabe anstatt Uart
die spannende ausgabe:
1
lcdCmd(clearDisplay); // LCD Command für Clear Display ausführen
Bild 2 liefert die Antwort: ja
..
Tip:
Der Inline ASM Code eigent sich auch hervoragend zur Eigenüberwachung,
Abgleich und andere.
lg
rudi ;-)
btw: Das bietet sich jetzt gerade zu an :)
Wer hat Lust auf eine Gegenüberstellung?
Xtensa ./. GCC
:)
wäre doch mal interessant?
hab beides da, werde für mich mal einfache beispiele ausprobieren und
bei zeiten dann mal per push posten.
Klar kann ich das auch noch machen:
Hier mal ein simples Contolling mit der API
1
uint32 system_get_time(void);
Ich bleib gleich bei dem Beispiel
und sende die time ergebnise jetzt einfach einmal per uart raus:
dazu ergänze ich jetzt
1
..
2
char wert3[32]; // für die formatierte uart ausgabe
3
4
..
5
unsigned t1; // API time variable 1
6
unsigned t2; // API time variable 2
7
..
bevor ich die ticks am start hole füge ich die api ein und hole den time
wert 1, nachdem der zweite tick wert eingelesen wurde nach den 100
durchläufen hole ich den time wert 2 und gebe ihn dann am schluss
formatiert auf den Uart aus.
1
t1 = system_get_time(); // API get time
2
// start
3
tick1 = get_ccount(); // Spezial Register CCOUNT Abruf und Übertrag
Abend,
das Display kannst auch im 4 Bit Modus direckt am ESP betreiben.
Mit dem MCP23S17 kann man schön einen Grafik Controller an SPI
betreiben.
Schau Dir ma z.B. den T6963C ist sehr verbreitet und gut zu gebrauchen.
Den must dann zwar im 8 Bit Modus betreiben aber das past dann schon.
Oder nimst einen SED133x Controller der kann auch eine höhre Auflösung.
Am ADC nimst 8 zu 1 Multiplexer für Touch.
Grafiken legst auf der SD Karte ab und lädst die nur bei bedarf nach
dann kannst auch Animierte Grafiken laufen lassen über SPI.
Naja den Rest schicke ich Dir dann per Mail will hier nicht deinen
Thraed Karpern.
Gruß
Ronny S. schrieb:> Abend,>> das Display kannst auch im 4 Bit Modus direckt am ESP betreiben.
Du Ganove :) kommst mir wieder zuvor! mit nibbles?
..
>> Mit dem MCP23S17 kann man schön einen Grafik Controller an SPI> betreiben.
ich hab den von adafruit 3.2" also 320 x 240, mit touch und sd
>> Schau Dir ma z.B. den T6963C ist sehr verbreitet und gut zu gebrauchen.
jo - genau
>> Den must dann zwar im 8 Bit Modus betreiben aber das past dann schon.>> Oder nimst einen SED133x Controller der kann auch eine höhre Auflösung.>> Am ADC nimst 8 zu 1 Multiplexer für Touch.
Du sprichst mir aus der Seele - 4051 hab ich vorgesehen, passt normal,
oder Ronny?
>> Grafiken legst auf der SD Karte ab und lädst die nur bei bedarf nach> dann kannst auch Animierte Grafiken laufen lassen über SPI.
aber bitte nicht die FW 0.9.5 nehmen, der wtd schlägt zu
ich bleib bei der 0.9.3 bis espressif eine komplette neue skd freigibt.
>> Naja den Rest schicke ich Dir dann per Mail
her damit - dann gehts los.
> will hier nicht deinen> Thraed Karpern.
he he - was sagst zur auflösung, reicht doch für ein oszi? oder nicht?
da bist du der fachmann! :)
:)
lg
rudi ;-)
Hallo Rudi,
immer eins nach dem anderen bis zum Mini Oszi für Audio ist da noch ein
weiter Weg für Dich.
Bringe erst mal ein Grafik Controller da sauber zum laufen am SPI und
dann entscheide was Du weiter machst damit.
Bau mal den T6963C erstmal ein in die Firmware mit einer Auflösung von
240x128 wenn das läuft sehen wir weiter was machbar ist.
Gruß
Ronny S. schrieb:> immer eins nach dem anderen bis zum Mini Oszi für Audio ist da noch ein> weiter Weg für Dich.
Na ja -
mein wifi 4chn osci läuft ja schon auf android
da nehm ich audio jack auch schon her :)
und der esp schaufelt schön die daten
( bild )
im moment lernt der espler pcm
http://www.ti.com/product/pcm1803a
und er lernt es schön :)
aber dazu mehr in Folge 6 :)
..
>> Bringe erst mal ein Grafik Controller da sauber zum laufen am> SPI und dann entscheide was Du weiter machst damit.
Ja ok - im Moment mach ich das mit dem MCP23S17 dazwischen, weil ich da
mehr Möglichkeiten habe, ok werde dann mal wieder zurückrudern und den
HW SPI nehmen. Aber nur weil du es bist :)
>> Bau mal den T6963C erstmal ein in die Firmware mit einer Auflösung von> 240x128 wenn das läuft sehen wir weiter was machbar ist.
puh - also ganz ehrlich ?
Bei mir laufen derzeit 1920 x 1080 -
warum willst du so winzig?
den T6963C glaub ich hatte ich doch schon -
es geht mittlerweilen : SSD1306 SSD1351 SSD1289 SSD1322 SSD1305
bevor wir den schönen Thread zuschaufeln lass uns das doch per mail
abstimmen, das ist ja ein FW Tip thread zu präzise timing
;-)
ticks: 49
10 x 2 x 2 = 40 + while 10 - 1 = 49 .. ok
Wer kommt drauf was zwischen durchlauf 1 und ab 2 anders ist?
;-)
lg
rudi ;-)
"hausaufgaben" müssen sein :)
10 x 2 x 2 = 40 + while 10 - 1 = 49
gegenprobe:
30 durchläufe
30 x 2 x 2 = 120 + while 30 - 1 = 149
und?
Bingo!
40 durchläufe
40 x 2 x 2 = 160 + while 40 - 1 = 199
und?
Bingo!
50 durchläufe
50 x 2 x 2 = 200 + while 50 - 1 = 249
und?
Bingo!
60 durchläufe
60 x 2 x 2 = 240 + while 60 - 1 = 299
und?
Bingo!
70 durchläufe
70 x 2 x 2 = 280 + while 70 - 1 = 349
und?
Bingo!
80 durchläufe
80 x 2 x 2 = 320 + while 80 - 1 = 399
und?
Bingo!
90 durchläufe
90 x 2 x 2 = 360 + while 90 - 1 = 449
und?
Bingo!
100 durchläufe
100 x 2 x 2 = 400 + while 100 - 1 = 499
und?
nö - 598
was ist mit den 100? und 598?
100 x 2 x 2 = 400 + while 100 - 1 = 499
wir haben aber 598?
also step by step
klammer wert ist rechnerischer soll
91 durchläufe = 454 ticks (91*2*2+while 91-1=454)
92 durchläufe = 459 ticks (92*2*2+while 92-1=459)
93 durchläufe = 464 ticks (93*2*2+while 93-1=464)
94 durchläufe = 469 ticks (94*2*2+while 94-1=469)
95 durchläufe = 474 ticks (95*2*2+while 95-1=474)
~~~~~~~~~~~~~~~bis hier her alles ok ~~~~~~~~~~~~~
mhm?
96 durchläufe = 574 ticks (96*2*2+while 96-1=479)
97 durchläufe = 580 ticks (97*2*2+while 97-1=484)
98 durchläufe = 586 ticks (98*2*2+while 98-1=489)
99 durchläufe = 592 ticks (99*2*2+while 99-1=494)
100 durchläufe = 598 ticks (100*2*2+while 100-1=499)
es sind in diesem 'abschnitt' immer 6 ticks mehr als vorherige wert
vorher waren es 5 ticks mehr.
zwischen 95 und 96 durchläufen 'kippt' es
auf
96*2*2+while 96-1 + 100-1
Ein Überlauf um 100 ticks und dann eine differenz weiterer werte um 6.
kippt es bei 2+95 also bei 96 + 95 = 191 durchäufen?
Test
190 durchläufe = 1138 ticks (190*2*2+while 190-1 + 190 - 1 = 1038 )
195 durchläufe = 1168 ticks (195*2*2+while 195-1 + 195 - 1 = 1168 )
200 durchläufe = 1198 ticks (200*2*2+while 200-1 + 200 - 1 = 1198 )
..
1200 ....= 7198 ( = 7198 )
nein, es kippt nicht mehr
warum kippt es bei 95-96?
warum ist es zwischen 1 und ab 2 Durchläufen anders?
Jemand eine Idee bevor Teil 2 'Überlauf' kommt?
:)
Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.
Wichtige Regeln - erst lesen, dann posten!
Groß- und Kleinschreibung verwenden
Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang