//PicoBasic V2.1 B.Kainka https://www.elektronik-labor.de/PicoBasic/TestLab.html
#include <EEPROM.h>
#include "hardware/pwm.h"

uint16_t code[256] = {0x4900};
uint32_t mask = 0x000000FF;
uint8_t ram[256];
uint8_t ram2[512];
uint8_t a = 0, b = 0, c = 0, d = 0;
uint8_t pw1=0;
uint8_t pw2=0;
uint16_t ad;
uint16_t rx = 1000;
char ch;
uint16_t adr = 0;
uint16_t return_adr[10];
uint16_t return_nr = 0;
uint16_t kom = 0;
uint16_t dat = 0;
uint32_t warten, weiter;

void setup() {
  Serial.begin(115200);
  EEPROM.begin(512);
}

void loop(){}

void setup1() {
  gpio_init_mask (mask);
  gpio_put_masked (mask, 0);
  gpio_set_function(8,GPIO_FUNC_PWM);
  gpio_set_function(9,GPIO_FUNC_PWM);
  pwm_config cfg = pwm_get_default_config();
  pwm_config_set_clkdiv_int (&cfg, 250);
  pwm_init(4, &cfg, true);
  pwm_set_wrap(4, 511);
  pwm_set_gpio_level(8,0);
  pwm_set_gpio_level(9,0);
  pwm_set_enabled(4,true);
}

void extensions(void){   
  if (dat==240){    //PWM Freq 
    uint8_t pre[11] = {250, 166, 125, 100, 50, 25, 20, 10, 5, 2, 1};
    pwm_set_enabled(4,false);
    pwm_config cfg = pwm_get_default_config();
    pwm_config_set_clkdiv_int (&cfg, pre[a]);
    pwm_init(4, &cfg, true);
    pwm_set_wrap(4, 511);
    pwm_set_gpio_level(8,pw1*2);
    pwm_set_gpio_level(9,pw2*2);
    pwm_set_enabled(4,true);
    warten = 20;  //Wartezeit 20 ms erforderlich. Warum??
  }
  if (dat==241){          //keine Uref                           
    pinMode(23,1);
    digitalWrite(23,1);   //Uregler Mode
  }
  if (dat==242){            //Hispeed Scope
    for (uint16_t n=0;n<256;n++){ram[n]=analogRead(A0) >>2;}
  }
  if (dat==243){            //Zweikanal Scope
    for (uint16_t n=0;n<256;n++){ram2[n*2]=analogRead(A0) >>2;
      ram2[n*2+1]=analogRead(A1) >>2;}
    for (uint16_t n=0;n<500;n++){Serial.println(ram2[n]);}
  }
  if (dat==244){            //Sinustabelle
    for (uint16_t n=0;n<256;n++){ram[n]=127+127*sin(3.14159*2*n/256);}
  }
  if (dat==245){            //DDS + Scope
    uint8_t akku = 0;
    for (uint8_t m=0;m<5;m++){      
      for (uint16_t n=0;n<512;n++){
        pwm_set_gpio_level(8,ram[akku]*2);
        akku += a;
        ram2[n]=analogRead(A0) >>2;
        //delayMicroseconds(1);
      }
    }
    for (uint16_t n=0;n<500;n++){Serial.println(ram2[n]);}
  }
  if (dat==246){      //Sweep
    uint8_t akku = 0;
    for (uint16_t n=0;n<512;n++){
      pwm_set_gpio_level(8,ram[akku]*2);
      akku = akku +a + (n>>4);
      ram2[n]=analogRead(A0) >>2;
      delayMicroseconds(11);
    }  
    for (uint16_t n=0;n<500;n++){Serial.println(ram2[n]);} 
  }
  if (dat==247){}
  if (dat==248){}
  if (dat==249){}
  if (dat==250){}
  if (dat==251){}
  if (dat==252){}
  if (dat==253){}
  if (dat==254){}
  if (dat==255){} 
}


  void k1(){a = dat;adr++;}  
  void k2(){b = dat;adr++;} 
  void k3(){c = dat;adr++;} 
  void k4(){d = dat;adr++;} 
  void np(){adr++;}    
  void k8(){gpio_put_masked (mask, dat);adr++;} //Pout dat
  void k9(){gpio_set_dir_masked (mask, dat);adr++;} //Pdir dat
  void k10(){for(int j=0; j<8; j++){gpio_set_pulls(j,1 &(dat>>j), 0);}adr++;} //Pullup dat  
  void k11(){for(int j=0; j<8; j++){gpio_set_pulls(j, 0,1 &(dat>>j));}adr++;} //Ppulldown dat  
   void k16(){pwm_set_gpio_level(8,dat*2); pw1=dat;adr++;} //PWM1 
  void k17(){pwm_set_gpio_level(9,dat*2); pw2=dat;adr++;} //PWM2 
  void k18(){a &= dat;adr++;} // A = A AND dat
  void k19(){a |= dat;adr++;} // A = A Or dat
  void k24(){delayMicroseconds(dat);adr++;} // Delay µs
  void k25(){warten = dat;adr++;}         // Dekay ms
  void k26(){warten = dat*1000;adr++;}    // Delay s
  void k27(){warten = dat*60000;adr++;}   // Delay min
  void k32(){adr++;adr = dat;} // Goto L
  void k33(){adr++;if (dat<240){return_nr++;return_adr[return_nr]=adr; adr = dat;}
      if (dat>239){extensions();}} // Gosub L  
  void k34(){adr++;if (a == b){adr = dat;};} // If A = B Goto L
  void k35(){adr++;if (a > b){adr = dat;};} // If A > B Goto L
  void k36(){adr++;if (a < b){adr = dat;};} // If A < B Goto L
  void k37(){adr++;if (c > 0){adr = dat;}; c--;} // C*Goto L 
  void k38(){adr++;if (d > 0){adr = dat;}; d--;} // D*Goto L   
  void k40(){a += 1;adr++;} // A = A + 1
  void k41(){a -= 1;adr++;} // A = A - 1
  void k42(){a += b;adr++;} // A = A + B
  void k43(){a -= b;adr++;} // A = A - B
  void k44(){a = a*b;adr++;} // A = A * B
  void k45(){a /= b;adr++;} // A = A / B
  void k46(){a &= b;adr++;} // A = A AND B
  void k47(){a |= b;adr++;} // A = A OR B
  void k48(){a = a^b;adr++;} // A = A XOR B
  void k49(){a = a << 1;adr++;} // A = Shl 1
  void k50(){a = a >> 1;adr++;} // A = Shr 1
  void k51(){a = ~a;adr++;} // A = NOT A
  void k52(){b = a;adr++;} // B = A
  void k53(){a = b;adr++;} // A = B
  void k54(){c = a;adr++;} // C = A
  void k55(){a = c;adr++;} // A = C
  void k56(){d = a;adr++;} // D = A
  void k57(){a = d;adr++;} // A = D
  void k58(){a = ram[b];b++;adr++;} // A = [B+] 
  void k59(){ram[b] = a;b++;adr++;} // [B+] = A  
  void k60(){a = analogRead(A0) >>2;adr++;} // A = AD0   
  void k61(){a = analogRead(A1) >>2;adr++;} // A = AD1   
  void k62(){a = analogRead(A2) >>2;adr++;} // A = AD2  
  void k63(){a = 255 & gpio_get_all();adr++;} // A = Pin   
  void k64(){a = 1 & (gpio_get_all());adr++;} // A = Pin0   
  void k65(){if(rx < 1000){a = rx; rx = 1000;}adr++;} // Input A    
  void k66(){Serial.println(a);adr++;} // Print A   
  void k67(){pwm_set_gpio_level(8,a*2); pw1=a;adr++;} // PWM1 = A  
  void k68(){pwm_set_gpio_level(9,a*2); pw2=a;adr++;} // PWM2 = A  
  void k69(){gpio_put_masked (mask, a);adr++;} // Pout = A 
  void k72(){adr++;adr = return_adr[return_nr]; return_nr--;} // Ret  
  void k73(){adr++;adr--;} // End  

  void d65(){Serial.println(a);}  //A
  void d66(){Serial.println(b);}  //B
  void d67(){Serial.println(c);}  //C
  void d68(){Serial.println(d);}  //D
  void d69(){Serial.println(analogRead(A0)>>2);}  //E  AD0
  void d70(){Serial.println(analogRead(A1)>>2);}  //F  AD1
  void d71(){Serial.println(analogRead(A2)>>2);}  //G  AD2
  void d72(){Serial.println(255 & gpio_get_all());} //H  Pin
  void d73(){weiter = 0xFFFFFFFF;} //I  Stop!
  void d74(){weiter = 0;} //J  Go!
  void d75(){uint16_t n = Serial.parseInt();gpio_set_dir_masked (mask, n);} //K  DIR
  void d76(){uint16_t n = Serial.parseInt();gpio_put_masked (mask, n);} //L  OUT
  void d77(){uint16_t n = Serial.parseInt();for(int j=0; j<8; j++){gpio_set_pulls(j,1 &(n>>j), 0);}} //M  Pullup
  void d78(){uint16_t n = Serial.parseInt();for(int j=0; j<8; j++){gpio_set_pulls(j, 0,1 &(n>>j));}} //N  Pulldown
  void d79(){uint16_t n = Serial.parseInt();pwm_set_gpio_level(8,n*2); pw1=n;} //O  PWM1
  void d80(){uint16_t n = Serial.parseInt();pwm_set_gpio_level(9,n*2); pw2=n;} //P  PWM2
  void d81(){for(int j=0; j<256; j++){uint16_t n = Serial.parseInt();ram[j]=n;}} //Q  RAM füllen
  void d82(){uint16_t n = Serial.parseInt();a = n;} //R  A=
  void d83(){uint16_t n = Serial.parseInt();b = n;} //S  B=
  void d84(){uint16_t n = Serial.parseInt();c = n;} //T  C=
  void d85(){uint16_t n = Serial.parseInt();d = n;} //U  D=
  void d86(){                                       //V  PWM-Vorteiler
    uint16_t n = Serial.parseInt();
    pwm_set_enabled(4,false);
    pwm_config cfg = pwm_get_default_config();
    pwm_config_set_clkdiv_int (&cfg, n);
    pwm_init(4, &cfg, true);
    pwm_set_wrap(4, 511);
    pwm_set_gpio_level(8,pw1*2);
    pwm_set_gpio_level(9,pw2*2);
    pwm_set_enabled(4,true);
  }

void loop1(){
  void (*befehl[76])() = {
  np, k1, k2, k3, k4, np, np, np, 
  k8, k9, k10, k11, np, np, np, np,
  k16, k17, k18, k19, np, np, np, np,
  k24, k25, k26, k27, np, np, np, np,
  k32, k33, k34, k35, k36, k37, k38, np,
  k40, k41, k42, k43, k44, k45, k46, k47,
  k48, k49, k50, k51, k52, k53, k54, k55,
  k56, k57, k58, k59, k60, k61, k62, k63,
  k64, k65, k66, k67, k68, k69, np, np,
  k72, k73, np};

  void (*direkt[22])() = {
  d65, d66, d67, d68, d69, d70, d71, d72, 
  d73, d74, d75, d76, d77, d78, d79, d80,
  d81, d82, d83, d84, d85, d86};
  
  for (adr = 0; adr < 255; adr++) {
    uint16_t eedat = (EEPROM.read(2*adr))<<8;        
    eedat = eedat + EEPROM.read(2*adr+1);
    if (eedat>0x4900){eedat=0x4900;}        
    code[adr] = eedat;
    weiter = 0; //keine Wartezeit
    warten = 0;
  } 
  adr=0;

  while(1){
    if (Serial.available() > 0){
      ch = Serial.read();
      delay(2);
      if (ch>47 && ch<58){
          rx = ch - 48;
        while (ch!=13){
          if (Serial.available() > 0){
            ch = Serial.read();
            if (ch>47 && ch<58){
              rx = rx * 10;
              rx = rx + ch - 48;
              rx = rx & 255;
            }
          }
        }
      Serial.println (rx);
      }    
      if (ch==112){   //p
        uint16_t n = Serial.parseInt();
        //Serial.println(ch); Serial.println(n);
        for (uint16_t i=0;i<n;i++){
          uint16_t pdat = Serial.parseInt();
          code[i] = pdat;
        }
        Serial.flush();
        adr = 0; 
        a=0; b=0; c=0; d=0;
        return_nr = 0;
        rx = 1000;
        weiter = 0; //keine Wartezeit
        warten = 0;
      }
      if (ch==101){   //e
        uint16_t n = Serial.parseInt();
        //Serial.println(ch); Serial.println(n);
        for (uint16_t i=0;i<n;i++){
          uint16_t pdat = Serial.parseInt();
          //Serial.println (pdat);
          code[i] = pdat;
          EEPROM.write(2*i, pdat>>8);
          EEPROM.write(2*i+1, pdat&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();
        adr = 0; 
        a=0; b=0; c=0; d=0;
        return_nr = 0;
        rx = 1000;
        weiter = 0; //keine Wartezeit
        warten = 0;
      }
      if (ch>64 && ch<88){
        direkt[ch-65]();
      }
    }
    if(warten>0){weiter = millis()+warten; warten = 0;}
    if(millis() >= weiter){
      kom = code[adr] >> 8;
      dat = code[adr] & 255;
      befehl[kom]();
    }
  }
}
