BicoBasic 3.1 mit Tastenprogrammierung

Elektronik-Labor  Projekte  Mikrocontroller  PicoBasic         




Firmware-Download: PicoBasic31TPS.zip

Video: https://www.youtube.com/watch?v=7lGBjn5Ljss

PicoBasic wird am PC programmiert und dann in den Controller übertragen. Dagegen kommt die TPS ganz ohne einen PC aus, weil man Programme direkt  über Tasten eingeben kann. Damit ist die Programmierung auch fernab aller Zivilisation möglich. Das wäre auch für einen PicoBasic-Controller eine gute Sache, dachte ich mir.  Mit dem Rpi Pico wurde die Tastenprogrammierung nun umgesetzt.

Der TPS-Controller braucht drei Tasten. Weil es ein 4-Bit-System ist, werden Zahlen bis 15 mit bis zu 15 Tastendrücken eingeben. PicoBasic ist aber ein 8-Bit-System. Bis zu 255 Tastendrücke wären unrealistisch. Deshalb wird hier eine bitweise Eingabe verwendet. Die Bits 0…7 werden nacheinander durch kurze und lange Tastendrücke programmiert. Kurz bedeutet, das Bit bleibt unverändert, und ein langer Druck invertiert es.

Für die Programmierung wird nur ein einziger Taster an GBIO15 gebraucht. Ein beliebig langer Tastendruck im Run-Modus schaltet in den Programmiermodus um. Alle Anzeigen verwenden die acht LEDs über Pullups, also mit reduzierter Helligkeit. Zuerst zeigen sie die aktuelle Adresse 0  durch ein schnelles, schwaches Flimmern aller LEDs an. Drückt man die Taste kurz, werden das Basic-Token und das Datenbyte kurz sichtbar. Danach erscheint die Adresse 1, wobei die erste LED heller ist. So kann man mit kurzen Tastendrücken durch ein vorhandenes Programm scrollen.

Wenn an einer Adresse die Daten überschrieben werden sollen, drückt man länger (ca. 0,5 s … 1 s) und löscht damit zugleich den Inhalt. Die Zeile enthält nun 0x0000, sodass nacheinander das Token 00 und das Datenbyte 00 programmiert werden müssen. Die Programmierung beginnt mit dem Bit 0, das gerade schwach blinkt. Mit einem kurzen Tastendruck bleibt es low, mit einem langen (ca. 0,5 s … 1 s) invertiert man es, es wird also high.  So geht man durch alle acht Bits, wobei das jeweils veränderbare Bit durch ein schnelles Blinken angezeigt wird. Das Byte wird nach und nach schichtbar. Falls man sich an einer Stelle vertippt hat, kann man noch einmal durch alle Bits gegen und nur das defekte Bit durch einen langen Druck invertieren. Wenn das Byte korrekt eingegeben ist, wechselt man durch einen sehr langen Tastendruck (ca. 1,5 s) in die Programmierung des Datenbytes. Das ist an jeder Stelle im Byte möglich.

Das Datenbyte wird genauso programmiert wie das Basic-Token. Mit einem sehr langen Druck (>1,5 s) beendet man die Eingabe. Weil viele Befehle kein Datenbyte brauchen, kann 00 stehen bleiben, und beendet die Eingabe sofort. Damit gelangt man wieder in die Anzeige der Adresse, die nun um eins erhöht wurde. So kann man nacheinander mehrere Zeilen ändern. Mit einem sehr langen Druck wechselt man in den Run-Modus und startet das aktuelle Programm.

So kann man kleine Änderungen an einem zuvor am PC erzeugten Programm mit nur einer Taste eingeben. Und man kann ein im RAM vorhandenes Programm ins EEPROM übertragen und damit Autostart-fähig machen. Dazu muss man im Adressen-Anzeigemodus 4 Sekunden lang auf den Taster drücken. Vom Run-Modus aus reichen zwei Tastendrücke, einmal kurz und einmal sehr, sehr lang.

Die Tastenprogrammierung eines vollständigen PicoBasic-Programms ist aufwendig und erfordert einige Übung. Man lernt dabei, in Binärzahlen zu denken. Weil man bei der Eingabe mit dem Bit 0 beginnt, muss man eine Binärzahl von rechts nach links übertragen. Das hat für kleine Zahlen den Vorteil, dass man nur wenige Bits eingeben muss. 0x02 bracht nur einen kurzen und einen längeren Tastendruck, danach kann man die Eingabe durch einen sehr langen Druck beenden.

Ein Beispiel:
0x09FF  Pdir = 255  wird binär zu
00001001  11111111  und erfordert die Eingaben
l k k l e        l l l l l l l l e  
(k = kurz, l = lang,  e = sehr lang für „Ende“)

Bei der Entwicklung der Tasteneingabe wurde intensiv nach den optimalen Zeiten für die Tastenbedienung gesucht. Am Ende kamen diese Werte dabei heraus:
Kleiner als 0,25 s: kurz    (weiter)
0,25 s bis 1,25 s: lang    (programmieren)
1,25 s bis 3 s: sehr lang    (beenden)
mehr als 3 s: sehr sehr lang (EEPROM)

In die aktuelle PicoBasic-Version für den Rpi Pico wurde die Tastenprogrammierung in Form einer einzelnen Funktion tps eingebaut.

void tps(){      //Programmierung über eine Taste an GPIO15
  gpio_set_dir_masked (mask, 0);        //Eingänge
  while (gpio_get(15) == 0){delay(100);} //Taste abwarten
  delay (100);
  adr = 0;
  int tps_running = 1;
  while (tps_running > 0){
    int pressed = 0;
    int done = 0;
    while (done == 0){  //adr-Anzeige und Tastenabfrage 50 ms
      for(int j=0; j<8; j++){gpio_set_pulls(j,1 &(255), 0);}
      delay (5);
      if (gpio_get(15) == 0){pressed++;}
      for(int j=0; j<8; j++){gpio_set_pulls(j,1 &(adr>>j), 0);}
      delay (45);
      if ((gpio_get(15) == 1) & (pressed > 0)){done = 1;}
    } 
    if (pressed < 5){   //Kurz < 250 ms: weiter
      uint16_t kom2 = code[adr] >> 8;
      uint16_t dat2 = code[adr] & 255;
      for(int j=0; j<8; j++){gpio_set_pulls(j,1 &(kom2>>j), 0);}
      delay (500);
      for(int j=0; j<8; j++){gpio_set_pulls(j,1 &(dat2>>j), 0);}
      delay (500);
    }
    if (pressed > 25){tps_running = 0;}  // >1,5s: TPS beenden

    if (pressed > 59){                 // 3s: EEPROM + beenden
      tps_running = 0;
      for (uint16_t i=0;i<256;i++){
        dat = code[i];
        EEPROM.write(2*i, dat>>8);
        EEPROM.write(2*i+1, dat&255);
        if (i==31){EEPROM.commit();}
        if (i==63){EEPROM.commit();}
        if (i==95){EEPROM.commit();}
        if (i==127){EEPROM.commit();}
        if (i==159){EEPROM.commit();}
        if (i==191){EEPROM.commit();}
        if (i==223){EEPROM.commit();}
      }
      Serial.flush();
      EEPROM.commit();
    } 
          
    if (pressed>4 && pressed <24){        // ca 1,5 s: kom ändern
      int done3 = 0;
      //kom = code[adr] >> 8;
      kom = 0;
      while (done3==0){     
        for(int i=0; i<8; i++){          //kom 0..7
          pressed = 0;
          int done2 = 0;
          while (done2==0){
            for(int j=0; j<8; j++){gpio_set_pulls(j,1 &(kom>>j), 0);}
            delay (40);
            if (gpio_get(15) == 0){pressed++;}
            gpio_set_pulls(i,1 & (~kom>>i), 0);
            delay (10);     
            if (gpio_get(15)==1 && pressed>0 && pressed<6){done2 = 1;} //<250ms: next bit         
            if (gpio_get(15)==1 && pressed>5 && pressed<25){  //ca.0,5s: Bit invertieren
              done2 = 1;
              kom = kom ^ (1<<i);
            }
            if (gpio_get(15)==1 && pressed>24){ //>1,5s:  fertig
              done2 = 1;
              done3 = 1;          
              i = 8;
            }
          }
        }
      }    

      done3 = 0;
      //dat = code[adr] & 8;
      dat = 0;
      while (done3==0){                // dat editieren
        for(int i=0; i<8; i++){          //dat 0..7
          pressed = 0;
          int done2 = 0;
          while (done2==0){
            for(int j=0; j<8; j++){gpio_set_pulls(j,1 &(dat>>j), 0);}
            delay (40);
            if (gpio_get(15) == 0){pressed++;}
            gpio_set_pulls(i,1 & (~dat>>i), 0);
            delay (10);     
            if (gpio_get(15)==1 && pressed>0 && pressed<6){done2 = 1;} //kurz: next bit         
            if (gpio_get(15)==1 && pressed>5 && pressed<25){    //ca.0,5s: Bit invertieren
              done2 = 1;
              dat = dat ^ (1<<i);
            }
            if (gpio_get(15)==1 && pressed>24){  // >1,25: fertig, next adr
              done2 = 1;
              done3 = 1;
              i = 8;
            }
          }
        }
      }
      code[adr] = kom*256 + dat;  //Geänderte Daten speichern
    }
    adr++;
 
  }
  delay(300);
  adr = 0;
  a=0; b=0; c=0; d=0;
  return_nr = 0;
  rx = 1000;
  weiter = 0; //keine Wartezeit
  warten = 0;
}



Elektronik-Labor  Projekte  Mikrocontroller  PicoBasic