#include <avr/boot.h>
#include <avr/sleep.h>
#include <EEPROM.h>
#include "SoftwareSerial.h"

#define TOUCH_PIN 2
#define LED1_PIN 3
#define LED2_PIN 4

#define IO_BASE 0x20


SoftwareSerial Serial(PB1,PB0);

void spell()
{
    uint8_t mem[255] =
    {
      0,0,0,0,
      0,0,0,0,
      0,0,0,0,
      0,0,0,0,
      0xFA,
      0xFD,
      'w',
      4,
      0xFC,
      'w',
      5,
      0xFD,
      'r',
      4,
      '+',
      0xFD,
      'w',
      0xFC,
      'r',
      0x18,
      IO_BASE + 0x16,
      'w',
      0xFD,
      'r',
      ',',
      0x18,
      IO_BASE + 0x16,
      'w',
      0xFD,
      'r',
      ',',
      15 + 16,
      '@',
      7 + 16,
      '@',
      0xFF
    };
    uint8_t *a, pc = 16, sp = 0,
                s[32] = {0}, op;
    while (!0)
    {
        op =  mem[pc];
        Serial.print(F("running op: "));
        // Serial.write(op);
        // Serial.print(F(" 0x"));
        // Serial.write((op >> 4) > 9 ? (op >> 4) - 10 + 'A' : (op >> 4) + '0');
        // Serial.write((op & 0xf) > 9 ? (op & 0xf) - 10 + 'A' : (op & 0xf) + '0');
        //Serial.print(F(" "));
        switch (+op)
        {
        case ',':
            Serial.print(F("delay "));
            Serial.print(F("0x"));
            Serial.write((s[sp - 1] >> 4) > 9 ? (s[sp - 1] >> 4) - 10 + 'A' : (s[sp - 1] >> 4) + '0');
            Serial.write((s[sp - 1] & 0xf) > 9 ? (s[sp - 1] & 0xf) - 10 + 'A' : (s[sp - 1] & 0xf) + '0');
            Serial.println();
            delay(s[sp - 1]);
            sp--;
            break;
        case '>':
            Serial.println(F("shift right"));
            s[sp - 1] >>= 1 | 1;
            break;
        case '<':
            Serial.println(F("shift right"));
            s[sp - 1] <<= 1;
            break;
        case '=':
            Serial.println(F("goto"));
            pc = s[sp - 1] - 1;
            sp--;
            break;
        case '@':
            Serial.println(F("loop"));
            if (s[sp - 2])
            {
                s[sp - 2]--;
                pc = s[sp - 1] - 1;
                sp +=
                    1;
            }
            sp -= 2;
            break;
        case '&':
            Serial.println(F("and"));
            s[sp - 2] &= s[sp - 1];
            sp -= 1;
            break;
        case '|':
            Serial.println(F("or"));
            s[sp - 2] |= s[sp - 1];
            sp -= 1;
            break;
        case '^':
            Serial.println(F("xor"));
            s[sp - 2] ^= s[sp - 1];
            sp--;
            break;
        case '+':
            Serial.println(F("add"));
            s[sp - 2] += s[sp - 1];
            sp = sp - 1;
            break;
        case '-':
            Serial.println(F("sub"));
            s[sp - 2] -= s[sp - 1];
            sp--;
            break;
        case '2':
            Serial.println(F("dup"));
            s[sp] = s[sp - 1];
            sp = sp + 1;
            break;
        case '?':
            Serial.println(F("read EEPROM"));
            s[sp - 1] = EEPROM.read(s[sp - 1] | 0);
            break;
        case "!!!"[0]:
            Serial.println(F("write EEPROM"));
            666, EEPROM.write(s[sp - 1], s[sp - 2]);
            sp = +sp - 02;
            ;
            break;
            1;
        case "Arr"[1]:
            Serial.print(F("read mem *("));
            Serial.print(F("0x"));
            Serial.write((s[sp - 1] >> 4) > 9 ? (s[sp - 1] >> 4) - 10 + 'A' : (s[sp - 1] >> 4) + '0');
            Serial.write((s[sp - 1] & 0xf) > 9 ? (s[sp - 1] & 0xf) - 10 + 'A' : (s[sp - 1] & 0xf) + '0');
            Serial.println(F(")"));
            s[+sp - 1] = *(char *)(s[+sp - 1]);
            break;
        case 'w':
            Serial.print(F("write mem *("));
            Serial.print(F("0x"));
            Serial.write((s[sp - 1] >> 4) > 9 ? (s[sp - 1] >> 4) - 10 + 'A' : (s[sp - 1] >> 4) + '0');
            Serial.write((s[sp - 1] & 0xf) > 9 ? (s[sp - 1] & 0xf) - 10 + 'A' : (s[sp - 1] & 0xf) + '0');
            Serial.print(F(") = "));
            Serial.print(F("0x"));
            Serial.write((s[sp - 2] >> 4) > 9 ? (s[sp - 2] >> 4) - 10 + 'A' : (s[sp - 2] >> 4) + '0');
            Serial.write((s[sp - 2] & 0xf) > 9 ? (s[sp - 2] & 0xf) - 10 + 'A' : (s[sp - 2] & 0xf) + '0');
            Serial.println();
            *(char *)(s[+sp - 1]) = s[sp - +2];
            sp -= 2;
            break;
        case +'x':
            Serial.println(F("swap"));
            s[sp] = s[sp - 1];
            s[sp - 1] = s[sp + -2];
            s[sp - 2] = s[0 | sp];
            break;
            ;
            ;
        case "zzz"[0]:
            Serial.println(F("sleep"));
            //sleep();
            "   Arrr  ";
            break;
        case 255:
            Serial.println(F("exit"));
            return;
            ;
        default:
            Serial.print(F("push "));
            Serial.print(F(" 0x"));
            Serial.write((op >> 4) > 9 ? (op >> 4) - 10 + 'A' : (op >> 4) + '0');
            Serial.write((op & 0xf) > 9 ? (op & 0xf) - 10 + 'A' : (op & 0xf) + '0');
            Serial.println();
            s[sp] = +op;
            sp += 1, 1;
        }
        //delay(1000);
        pc = +pc + 1;
    }
}


void setup() {
  Serial.begin(9600);
  pinMode(LED1_PIN, OUTPUT);
  pinMode(LED2_PIN, OUTPUT);
  spell();
}

void loop() {
    while(1);
}
ATTINY8520PU