nun, hmm, da bräuchte ich jetzt tatkräftige Hilfe von jemandem mit richtig viel Kenne, wie man das jetzt zur Problemlösung einsetzt ...
Die Doku dazu ist hauptsächlich als simpler Text verfügbar und auch nicht gerade Umfangreich, da das ohne lib kaum jemand benutzt.
https://www.kernel.org/doc/Documentation/input/
input und input-programming dürften interessant sein.
- - - Aktualisiert - - -
Die Doku dazu ist hauptsächlich als simpler Text verfügbar und auch nicht gerade Umfangreich, da das ohne lib kaum jemand benutzt.
https://www.kernel.org/doc/Documentation/input/
input und input-programming dürften interessant sein.
nun, hmm, da bräuchte ich jetzt tatkräftige Hilfe von jemandem mit richtig viel Kenne, wie man das jetzt zur Problemlösung einsetzt ...
Hallo,
Eigentlich ist es genau umgekehrt! :-P
Normal ist, dass LF (LineFeed,"\n") eben NUR das Papier um eine Zeile weiter transportiert.
Entsprechend fährt CR (CarriageReturn, "\r") eben nur den Wagen nach links.
Das "\n" in CR LF übersetzt wird ist die "Verzerrung".
Aber bei Unix kann dies alles unter TTY eingestellt werden.
Früher brauchte man LF, BS usw. als Coursorsteuerung.
Zudem konnte man auf einem einfachen TTY mit CR Fettdruck erreichen, indem man den selben Text mehrmals übereinander gedruckt hat.
TTY ist das was man als Fernschreiber kennt. Bis so etwa Mitte der 70er war dies das normale Ein/Ausgabegerät für Computer. Drucker waren damals noch sehr Teuer. So 1978 brachte Centronics den Low Costdrucker 779 heraus, kostete damals um die CHF 4'800.-- und war ein A4-Hochformat 7-Nadeldrucker mit Stachelwalzen, ohne Unterlängen, und schaffte 40 Zeichen/s (eigentlich 80Z/s aber er druckte nur unidirektional und der Rücklauf war gleich schnell wie der Druck). Gaphik konnte der auch noch nicht drucken, nur ASCII-Zeichen.
Etwas später kam dann Epson mit dem RX 80 (CHF 1'800.--) als A4 Hoch und RX 100 (A4 quer).
Zur damaligen Zeit gab es eine billige Typenrad-Schreibmaschine, welche man einfach zu einem Drucker umbauen konnte. Allerdings war diese langsam und mechanisch nicht für hundertseitige Listings ausgelegt. Die lebten dann meistens nicht sehr lange.
MfG Peter(TOO)
Manchmal frage ich mich, wieso meine Generation Geräte ohne Simulation entwickeln konnte?
printf("\n") macht in C standardmäßig ein LF und ein CR, sowohl auf Arduinos als auch auf Raspi-LX-Terminals. Das ist der Standard.
Das ist aber nicht der Punkt, und deinen Historienwissenserguss in allen Ehren - es ist OT und hilft nicht bei der Problemlösung, denn es sind Scancodes gefragt, die man einfach aus einem C Programm heraus zur Sondertastenerkennung benutzen kann.
Selbst da aber versagt ncurses, unabhängig von dem Terminal-Anzeige-Problem, denn es erkennt ja kaum welche in Kombi mit den modifiern, und ich brauche und will auch gar kein extra-Terminal.
Auch geht es ja gar nicht um stdout, sondern stdin, denn daraus liest ja auch mein getchar (stdio.h) und mein tcgetattr aus termio.h.
wie nützt man nun also, alternativ, z.B.
https://www.kernel.org/doc/Documentation/input/
oder auch jeden anderen gangbaren und praktikablen Weg?
Hallo,
man kann alle Tasten in C abfragen. Du kannst sogar auf die Numlock-Taste im Programm reagieren.
Anbei ein auf das Wesentliche reduzierte Testprogramm:Dieses Programm zeigt die Codes an, welche an einer AM RASPI ANGESCHLOSSENEN Tastatur gedrückten / losgelassenen Taste entspricht. Ein Beispiel mit F1 ohne und mit SHIFT habe ich eingefügt.Code:// Compile with: GCC -o /var/scripte/tastaturtest /var/scripte/tastaturtest.c -L/usr/local/lib -lpthread //nice -1 /var/scripte/tastaturtest < /dev/input/event0 & #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <stdint.h> #include <sys/sysinfo.h> #include <time.h> #include <linux/input.h> #include <pthread.h> int ziffer=0; int beenden=2; int zeit=0; int shiftl=0; int shiftr=0; int strgl=0; int strgr=0; int capsl=0; unsigned char runterfahren(){ system("halt"); } unsigned char zahlentaste() { printf("Zahlentaste: %d\n", ziffer); } unsigned char tnull() { ziffer=0; zahlentaste(); } unsigned char teins() { ziffer=1; zahlentaste(); } unsigned char tzwei() { ziffer=2; zahlentaste(); } unsigned char tdrei() { ziffer=3; zahlentaste(); } unsigned char tvier() { ziffer=4; zahlentaste(); } unsigned char tfuenf() { ziffer=5; zahlentaste(); } unsigned char tsechs() { ziffer=6; zahlentaste(); } unsigned char tsieben() { ziffer=7; zahlentaste(); } unsigned char tacht() { ziffer=8; zahlentaste(); } unsigned char tneun() { ziffer=9; zahlentaste(); } unsigned char tdel() { printf("Delete\n"); } unsigned char tnum() { printf("Numlock\n"); } unsigned char tenter() { printf("Enter\n"); } unsigned char tplus() { printf("Plus\n"); } unsigned char tminus() { printf("Minus\n"); } unsigned char tmal() { printf("Mal\n"); } unsigned char tgeteilt() { printf("Geteilt\n"); } unsigned char tbs() { printf("Backspace\n"); } unsigned char tq() { beenden=1; } unsigned char status() { printf("SHIFTL: %d, SHIFTR: %d, STRGL: %d, STRGR: %d\n",shiftl,shiftr,strgl,strgr); } unsigned char tf1() { if(shiftl>=1 || shiftr>=1){ printf("SHIFT + F1\n"); }else{ printf("F1\n"); } } void tastatur(void *name) { struct input_event event; while ((read(0, &event, sizeof(event)) > 0) && (beenden==2) ) { if (event.type != EV_KEY) continue; // if (event.value != EV_KEY) continue; //Nur Tastendrücke erkennen, kein Loslassen. 0=losgelassen, 1=gedrückt, 2=Wiederholung(lang gedrückt) printf("Typ: %d; Wert: %d; Code: %d\n",event.type,event.value,event.code); switch (event.code) { case 42: shiftl=event.value; break; case 54: shiftr=event.value; break; case 29: strgl=event.value; break; case 97: strgr=event.value; break; case 16: tq(); break; //q case 82: tnull(); break; //0 case 79: teins(); break; //1 case 80: tzwei(); break; //2 case 81: tdrei(); break; //3 case 75: tvier(); break; //4 case 76: tfuenf(); break; //5 case 77: tsechs(); break; //6 case 71: tsieben(); break; //7 case 72: tacht(); break; //8 case 73: tneun(); break; //9 case 83: tdel(); break; //DEL case 96: tenter(); break; //ENTER case 78: tplus(); break; //+ case 74: tminus(); break; //- case 55: tmal(); break; //* case 98: tgeteilt(); break; /// case 14: tbs(); break; //Backspace case 69: tnum(); break; //NumLock case 59: tf1(); break; //F1 case 31: status(); break; //s } } beenden=0; pthread_exit((void *) 0); } int main(int argc, char** argv) { pthread_t t1; if(pthread_create(&t1, NULL, (void *)&tastatur, (void *)"Tastatur") != 0) { fprintf(stderr, "Fehler bei Tastatur......\n"); exit(0); } while (beenden > 0) { sleep(1); zeit++; if (zeit==30) { zeit=0; printf("Wieder 30 Sekunden um.\n"); } } usleep(50); printf("***********Ende************\n"); return 0; }
Das Programm wird mit q beendet. Als Startparameter muss das Device der Tastatur angegeben werden. Bei nur einer Tastatur reicht die zweite Zeile im Programmkopf zum Starten. Den Pfad (auch den zum zum kompilieren) natürlich anpassen.
Wenn das Herz involviert ist, steht die Logik außen vor! \/
hallo,
super, das sieht ja sehr beeindruckend aus!
ich verwende Geany zum Kompilieren und habe da auch die compile- und Build- Parameter fest eingestellt.
Mit make etc. stehe ich auf dem kriegsfuß...
Ich verwende g++, nicht gcc, dürfte aber sicher kein Problem sein.
-pthread
hab ich schon drin
-L/usr/local/lib
muss sicher noch dazu
was sonst noch? den rest verstehe ich nämlich nicht.
bekomme sehr viele Fehlermeldungen
printf not declared => #include <stdio.h> eingefügt.
system not declared => ???
exit not declared => ???
int main(int argc, char** argv) geändert in
int main()
die Zeile mit if( pthread_create....) hat einen dicken Fehler
invalid conversion from void* to void*(*)(void*)
if kann man sicher doch ganz weglassen!!
Ich initialisiere immer nur per
pthread_create(&threadID, NULL, threadName, NULL);
Startparameter kann ich nicht eingeben!
Geändert von HaWe (05.04.2016 um 20:36 Uhr)
Hallo,
die Includes könnten mehr sein als notwendig sind. Das frisst aber kein Brot und in meinem Programm, wo ich das meiste rauskopiert habe, brauche ich diese. Geany sagt mir leider gar nichts. Ich kompiliere mit gcc. Der Aufruf dafür steht ja in der ersten Zeile.
Dann kommen die Variablen für die 'Sondertasten'. Wobei ich für Capslock kein Beispiel reinprogrammiert habe.
Je nach Tastencode (Scancode?) wird die dazugehörige Sub aufgerufen. Da braucht man natürlich nur die Codes der Tasten abfragen, die tatsächlich genutzt werden. Wird freie Texteingabe unterstützt, muss man das nachbauen.
Wird q gedrückt, wird zuerst der zweite Thread beendet und dann 50 Mikrosekunden später das Hauptprogramm. Schmiert das ab, dann bleibt der Thread am Leben. Ist aber nicht tragisch. GCC beendet den beim nächsten kompilieren automatisch
Die 30 Sekunden Wartezeit sollen nur demonstrieren, dass das Hauptprogramm weiterläuft, auch wenn keine Taste gedrückt wird.
Ansonsten wird hhalt bei jedem Tastendruck die zugehörige Sub aufgerufen. Das Hauptprogramm und der zweite Thread teilen sich die globalen Variablen.
Edit:
Bei mir kompiliert er fehlerfrei. Hast Du gcc? Ich starte mal den Raspi und schaue, welche Pakete so drauf sind.
Geändert von peterfido (05.04.2016 um 20:58 Uhr)
Wenn das Herz involviert ist, steht die Logik außen vor! \/
nein, g++
und Startparameter kann ich nicht eingeben!
das Device der Tastatur kenne ich nicht
ich kann nicht ohne Geany compilieren. Kommandozeile kann ich nicht.
die includes stören mich nicht, aber bei dir fehlte stdio.h !
und wohl noch ein wenig mehr wegen system und exit
hier ist der Link zu meinem kompletten Programm, wo alles mit rein muss, nur zur Info:
http://www.mindstormsforum.de/viewto...p=69043#p69089
Geany-Build-Parameter:
g++ -Wall -pthread -I/opt/vc/include -I/opt/vc/include/interface/vmcs_host/linux -I/opt/vc/include/interface/vcos/pthreads -o "%e" "%f" -lshapes -L/opt/vc/lib -lOpenVG -lEGL -lwiringPi -lrt
Geändert von HaWe (05.04.2016 um 20:46 Uhr)
Hallo,
stdio.h ist doch drin. Das erste Include gleich. (Siehe Post #15). Ob g++ auch C-Code kompilieren kann, weiß ich nicht. Ich progge nur in C (BASH / PHP mal außen vor) und alles per Kommandozeile. Wie gesagt, Geany habe ich nicht. Die installierten Pakete liste ich doch nicht auf. Es sind 846 Pakete.
Ich hänge mal meine fertig compilierte Datei hier an. Evtl. hilft sie Dir die Scancodes auszulesen. Die Datei ist unter Windows gepackt und muss auf den Raspi. Die Rechte auf 755 setzen und starten.
Wenn Du sie, wie im Quellcodekopf, mit nice startest, dann läuft sie mit geringerer Priorität. Das & am Ende bedeutet, dass das Programm im Hintergrund ausgeführt wird und die Konsole für andere Dinge genutzt werden kann.
Mehr kann ich da leider nicht für Dich tun. Die nächste Zeit bin ich erstmal hauptsächlich offline und komme auch nicht zum basteln.
Edit: Bei Dir steht zwar -pthread im Parameter, bei mir jedoch -lpthread. Also scheint es da Unterschiede zu geben. Probiere mal nur meinen Code zu compilieren, ohne ihn irgendwo einzubauen.
Edit 2:
int main(int argc, char** argv) ist für die angegebenen Parameter wichtig. Evtl. will Geany für die Fensteroberfläche kompilieren. Schau mal, ob man da auch ein Konsolenprogramm als Typ auswählen kann.
Geändert von peterfido (05.04.2016 um 21:03 Uhr)
Wenn das Herz involviert ist, steht die Logik außen vor! \/
war ein copy + paste Fehler mit den #includes.
Leider verstehe ich deinen Code nicht, es muss in meinen Task reinpassen, der läuft mit mittlerer prio, und darum geht es ja letztendlich:
Das auslesen müsste darin laufen, und die Art der gedrückten Taste könnte genau wie meine Meldungen bei ESC (analog per printf) in der Konsole angezeigt werden.Code:void* thread1Go(void *) // medium priority: keyboard + heartbeat monitoring { int c; // keyboard key while(_TASKS_ACTIVE_) { c=0; if (kbhit()) { // <<<<<<<<<<<<<<<<<< c = getchar(); if( c==27 ) { // ESC to quit program printf("\n\n ESC pressed - program terminated by user \n"); _TASKS_ACTIVE_=0; // semaphore to stop all tasks printf("\n wait for tasks to join main()... \n\n"); return NULL; } else if( ) { } //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< dein Code } //... ***SNIP*** delay(50); } return NULL; }
Konsolenprogramm soll nicht sein, ist meines auch nicht!
http://www.mindstormsforum.de/viewto...p=69043#p69089
Code:int main() { char sbuf[128]; int err; // **SNIP** pthread_t thread0, thread1, thread2, thread3, thread4, thread5; struct sched_param param; pthread_create(&thread0, NULL, thread0Go, NULL); // lowest priority task: screen output param.sched_priority = 10; pthread_setschedparam(thread0, SCHED_RR, ¶m); pthread_create(&thread1, NULL, thread1Go, NULL); // low priority: keyboard monitoring (stop program) param.sched_priority = 20; pthread_setschedparam(thread1, SCHED_RR, ¶m); pthread_create(&thread2, NULL, thread2Go, NULL); // medium priority: motor control param.sched_priority = 40; pthread_setschedparam(thread2, SCHED_RR, ¶m); pthread_create(&thread3, NULL, thread3Go, NULL); // highest priority: encoder reading param.sched_priority = 80; pthread_setschedparam(thread3, SCHED_FIFO, ¶m); pthread_create(&thread4, NULL, thread4Go, NULL); // medium priority: UART comm <<< test !! param.sched_priority = 40; pthread_setschedparam(thread4, SCHED_FIFO, ¶m); pthread_create(&thread5, NULL, thread5Go, NULL); // medium priority: navigation param.sched_priority = 40; pthread_setschedparam(thread1, SCHED_FIFO, ¶m); //... **SNIP** }
Geändert von HaWe (05.04.2016 um 21:41 Uhr)
Lesezeichen