//PicoBasic Nano V2.3 
#include <EEPROM.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;
uint16_t n;
uint16_t ad;
uint16_t rx = 1000;
char ch;
uint8_t adr = 0;
uint8_t return_adr[128];
uint8_t return_nr = 0;
uint8_t kom = 0;
uint8_t dat = 0;
uint32_t warten, weiter, Timer_hi;
uint8_t uref = 0x60;


uint8_t adc(uint8_t ch){
  ADMUX = uref+ch; 
  ADCSRA = 0xC5;  //Start, 0,5 MHz (Update 27.5.25) 
  while((ADCSRA & 0x40)); 
  return ADCH;  
}

void USART_sendChar(char c){
  while ( !( UCSR0A & (1<<UDRE0)));
  UDR0 = c;
}

void USART_printByte(uint8_t n){
    if (n>99){
      while ( !( UCSR0A & (1<<UDRE0)));
      UDR0 = 48+n/100;
      n=n-100*(n/100);
      while ( !( UCSR0A & (1<<UDRE0)));
      UDR0 = 48+n/10;
      n=n-10*(n/10);
      while ( !( UCSR0A & (1<<UDRE0)));
      UDR0 = 48+n;
    }
    else{
      if (n>9){
        while ( !( UCSR0A & (1<<UDRE0)));
        UDR0 = 48+n/10;
        n=n-10*(n/10);
      }
      while ( !( UCSR0A & (1<<UDRE0)));
      UDR0 = 48+n;
    }
    while ( !( UCSR0A & (1<<UDRE0)));
    UDR0 = 13;
    while ( !( UCSR0A & (1<<UDRE0)));
    UDR0 = 10;
}

char USART_readChar(void){
  while ( !(UCSR0A & (1<<RXC0)) );
  return UDR0;
}

void USART_flush(void){
  char c;
  //delay(1);
  if (UCSR0A & (1<<RXC0)){c=UDR0;}
  if (UCSR0A & (1<<RXC0)){c=UDR0;}
  if (UCSR0A & (1<<RXC0)){c=UDR0;}
}

uint16_t USART_readInt(void){
  char c;
  uint16_t n=0;
  while ( !(UCSR0A & (1<<RXC0)) );;
  c= UDR0; 
  while (c > 13){
    if (c>47 && c<58){
      n=n*10;
      n+=c-48;
    }
    while ( !(UCSR0A & (1<<RXC0)) );;
    c= UDR0; 
  }
   return n;
}

void extensions(void){
  if (dat==240){                    //PWM Freq 
    if (a==4) {TCCR2B=1;TCCR1B=1;}  //Prescaler 1
    if (a==3) {TCCR2B=2;TCCR1B=2;}  //Prescaler 8
    if (a==2) {TCCR2B=4;TCCR1B=3;}  //Prescaler 64
    if (a==1) {TCCR2B=6;TCCR1B=4;}  //Prescaler 256
    if (a==0) {TCCR2B=7;TCCR1B=5;}  //Prescaler 1014}  
  }
  if (dat==241){                    //AD Ref
    if (a==0) {uref=0xE0;}  //Ref 1.1 V
    if (a==1) {uref=0x20;}  //Ref ext 
    if (a==2) {uref=0x60;}  //Ref 5 V 
  }  
  if (dat==242){            //Highspeed Scope
    for (n=0;n<256;n++){
      ram[n]=adc(0);
    }
  }
  if (dat==243){            //Zweikanal Scope
    for (uint16_t n=0;n<256;n++){ram2[n*2]=adc(0);ram2[n*2+1]=adc(1);}
    for (uint16_t n=0;n<500;n++){USART_printByte(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 125 kHz
    uint8_t akku = 0;
    uint8_t t = 0;
    adc(0);
    ADCSRA = 0xC3;  //Start, 2 MHz 
    for (uint8_t m=0;m<5;m++){      
      for (uint16_t n=0;n<512;n++){
        OCR1BL = ram[akku]; akku += a;
        while((ADCSRA & 0x40)); 
        ram2[n]=ADCH;
        __asm__("nop\n\t");__asm__("nop\n\t");__asm__("nop\n\t");
        ADCSRA = 0xC3;  //Start, 2 MHz 
      }
    }
    for (uint16_t n=0;n<500;n++){USART_printByte(ram2[n]);}
  }
  if (dat==246){      //Sweep 50 kHz
    uint8_t akku = 0;
    for (uint16_t n=0;n<512;n++){
      OCR1BL = ram[akku]; 
      akku = akku +a + (n>>4);
      ram2[n]=adc(0);
      delayMicroseconds(3);
    }  
    for (uint16_t n=0;n<500;n++){USART_printByte(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 k8(){PORTD=(dat<<2)+3;PORTB=(PORTB&252)|(dat>>6); adr++;}  //Pout dat
 void k9(){DDRD=(dat<<2)+2;DDRB=(DDRB&252)|(dat>>6); adr++;}   //Pdir dat                
 void k10(){adr++;} //Pullup dat; Neim Nano über Port und Pdir                     
 void k11(){adr++;} //Ppulldown dat, nicht beim Nano 
    
  void k16(){OCR1BL=dat;adr++;} //PWM1 
  void k17(){OCR2A =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++;}        // Delay 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 = adc(0);adr++;} // A = AD0   
  void k61(){a = adc(1);adr++;} // A = AD1   
  void k62(){a = adc(2);adr++;} // A = AD2  
  void k63(){a = (PINB<<6)+(PIND>>2);adr++;} // A = Pin   
  void k64(){a = 1 & (PIND>>2);adr++;} // A = Pin0   
  void k65(){if(rx < 1000){a = rx; rx = 1000;}adr++;} // Input A    
  void k66(){USART_printByte(a);adr++;} // Print A   
  void k67(){OCR1BL=a;adr++;} // PWM1 = A  
  void k68(){OCR2A=a;adr++;} // PWM2 = A  
  void k69(){PORTD=(a<<2)+3;PORTB=(PORTB&252)|(a>>6); adr++;} // Pout = A
  void k70(){}
  void k71(){}
  void k72(){adr++;adr = return_adr[return_nr]; return_nr--;} // Ret  
  void k73(){adr++;adr--;} // End  
  void np(){adr++;}    
  
  void d65(){USART_printByte(a);} //A
  void d66(){USART_printByte(b);} //B
  void d67(){USART_printByte(c);} //C
  void d68(){USART_printByte(d);} //D
  void d69(){USART_printByte(adc(0));}  //E  AD0
  void d70(){USART_printByte(adc(1));}  //F  AD1
  void d71(){USART_printByte(adc(2));}  //G  AD2
  void d72(){USART_printByte(((PINB<<6)+(PIND>>2))&255);} //H  Pin
  void d73(){weiter = 0xFFFFFFFF;} //I  Stop!
  void d74(){weiter = 0;} //J  Go!
  void d75(){n = USART_readInt();DDRD=(n<<2)+2;DDRB=(DDRB&252)|(n>>6);} //K  DIR
  void d76(){n = USART_readInt();PORTD=(n<<2)+3;PORTB=(PORTB&252)|(n>>6);} //L  OUT
  void d77(){n = USART_readInt();} //M  Pullup
  void d78(){n = USART_readInt();} //N  Pulldown
  void d79(){n = USART_readInt();OCR1BL= n;} //O  PWM1
  void d80(){n = USART_readInt();OCR2A = n;} //P  PWM2
  void d81(){for(int j=0; j<256; j++){uint16_t n = USART_readInt();ram[j]=n;}} //Q  RAM füllen
  void d82(){n = USART_readInt();a = n;} //R  A=
  void d83(){n = USART_readInt();b = n;} //S  B=
  void d84(){n = USART_readInt();c = n;} //T  C=
  void d85(){n = USART_readInt();d = n;} //U  D=
  void d86(){                                     //V PWM-Freq
    n = USART_readInt();
    if (n==4) {TCCR2B=1;TCCR1B=1;}  //Prescaler 1
    if (n==3) {TCCR2B=2;TCCR1B=2;}  //Prescaler 8
    if (n==2) {TCCR2B=4;TCCR1B=3;}  //Prescaler 64
    if (n==1) {TCCR2B=6;TCCR1B=4;}  //Prescaler 256
    if (n==0) {TCCR2B=7;TCCR1B=5;}  //Prescaler 1014
  }
    void d87(){                                   //W ADC Ref
    n = USART_readInt();
    if (n==0) {uref=0xE0;}  //Ref 1.1 V
    if (n==1) {uref=0x20;}  //Ref ext 
    if (n==2) {uref=0x60;}  //Ref 5 V 
  }

  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[23])() = {
  d65, d66, d67, d68, d69, d70, d71, d72, 
  d73, d74, d75, d76, d77, d78, d79, d80,
  d81, d82, d83, d84, d85, d86, d87};

   
int main(void){
  UBRR0H = 0;     //USART
  UBRR0L = 0;     //1: 500kBaud, 0: 1 MBaud
  UCSR0B = 0x18;  //TX, RX an
  UCSR0C = 0x06;  //8N1
  ADMUX = 0x60;   //Ref = VCC, Left adjusted 
  ADCSRA = 0xC4;  //1. Start, 1 MHz     
  while((ADCSRA & 0x40)); 
  TCCR1A = 0x21;  //PWM, Phase Correct, 8-bit
  TCCR1B = 3;
  OCR1BL = 0;
  TCCR2A = 0x81;  //PWM, Phase Correct, 8-bit
  TCCR2B = 4;
  OCR2A = 0;
  DDRB = 0x0C;    //PWM outputs
  TCCR0A = 0x02;  // CTC-Modus
  OCR0A = 249;    //1 ms
  TCCR0B = 3;     //16MHz /64 = 250 kHz
  TCNT0 = 0;

  for (adr = 0; adr < 255; adr++) {
    uint16_t data = (EEPROM.read(2*adr))<<8;        
    data = data + EEPROM.read(2*adr+1);    
    if (data>0x4A00){data=0x4A00;}    
    code[adr] = data;
  } 
  adr=0;
  weiter = 0; //keine Wartezeit
  warten = 0;
  TCCR0B = 0; //ms-Counter abschalten

  while(1){
    if (UCSR0A & (1<<RXC0)){
      ch = USART_readChar();
      if (ch>47 && ch<58){
        //if (rx==1000){
          rx = ch - 48;
        //}
        while (ch!=13){
          if (UCSR0A & (1<<RXC0)){
            ch = USART_readChar();
            if (ch>47 && ch<58){
              rx = rx * 10;
              rx = rx + ch - 48;
              rx = rx & 255;
            }
          }
        }
      USART_printByte (rx);
      }    
      if (ch==112){   //p
        uint16_t n = USART_readInt();
        //Serial.println(ch); Serial.println(n);
        for (uint16_t i=0;i<n;i++){
          uint16_t pdat = USART_readInt();
          //Serial.println (pdat);
          code[i] = pdat;
        }
        USART_flush();
        adr = 0; 
        a=0; b=0; c=0; d=0;
        return_nr = 0;
        rx = 1000;
        weiter = 0; //keine Wartezeit
        warten = 0;
        TCCR0B = 0; //ms-Counter abschalten
      }
      if (ch==101){   //e
        uint16_t n = USART_readInt();
        //Serial.println(ch); Serial.println(n);
        for (uint16_t i=0;i<n;i++){
          uint16_t pdat = USART_readInt();
          code[i] = pdat;
          EEPROM.write(2*i, pdat>>8);
          EEPROM.write(2*i+1, pdat&255);
        }
        USART_flush();
        adr = 0; 
        a=0; b=0; c=0; d=0;
        return_nr = 0;
        rx = 1000;
        weiter = 0; //keine Wartezeit
        warten = 0;
        TCCR0B = 0; //ms-Counter abschalten
      }
      if (ch>64 && ch<89){
        direkt[ch-65]();
      }      
    }
    if(warten>0){weiter = Timer_hi + warten; warten = 0; TCCR0B=3;}
    if (TIFR0&(1<<OCF0A)){Timer_hi++; TIFR0 |=(1<<OCF0A);}
    if(Timer_hi >= weiter){
      kom = code[adr] >> 8;
      dat = code[adr] & 255;
      befehl[kom]();
    }
  }
}
