diff --git a/ESP_ILI9341_game_engine.ino b/ESP_ILI9341_game_engine.ino new file mode 100644 index 0000000..d9c44e2 --- /dev/null +++ b/ESP_ILI9341_game_engine.ino @@ -0,0 +1,213 @@ +#include +#include +#include +#include +#include +#include +#include +ADC_MODE(ADC_VCC); + +// Use hardware SPI +TFT_eSPI tft = TFT_eSPI(); +#define RAM_SIZE 20 * 1024 + +// ------------------begin ESP8266'centric---------------------------------- +#define FREQUENCY 160 // valid 80, 160 +// +#include "ESP8266WiFi.h" +extern "C" { + #include "user_interface.h" +} +// ------------------end ESP8266'centric------------------------------------ +int voltaje=0; +byte i2c_adress; +byte thiskey; +Ticker timer; +uint16_t cadr_count; +unsigned long timeF,timeR; +int timeCpu = 0,timeGpu = 0,timeSpr = 0,cpuOPS = 0; +byte fps; +volatile uint16_t timers[8]; +uint8_t mem[RAM_SIZE] = {0x12,0x00,0x06,0x20,0x99,0x03,0x90,0x00,0x18,0x02,0x11,0x02,0xD4,0x51,0x12,0x00,0x06,0x20,0x97,0x03,0x31,0x01,0x97,0x03,0x12,0x08,0xC1,0x12,0xC2,0x12,0xB1,0x00,0x92,0x00,0x92,0x00,0x01,0x02,0x62,0x03,0x82,0x02,0x31,0x02,0x97,0x03,0x13,0x10,0xA4,0x23,0x82,0x02,0x12,0x50,0x82,0x02,0x12,0x08,0x82,0x02,0x12,0x08,0x82,0x02,0x99,0x00,0x30,0x02,0xA8,0xA0,0x01,0x02,0x40,0x03,0x82,0x02,0x31,0x02,0x97,0x03,0x13,0x10,0xA4,0x23,0x82,0x02,0x12,0x60,0x82,0x02,0x12,0x08,0x82,0x02,0x12,0x08,0x82,0x02,0x99,0x00,0x30,0x02,0xA8,0xA0,0x01,0x02,0x40,0x03,0x82,0x02,0x31,0x02,0x97,0x03,0x13,0x10,0xA4,0x23,0x82,0x02,0x12,0x70,0x82,0x02,0x12,0x08,0x82,0x02,0x12,0x08,0x82,0x02,0x99,0x00,0x30,0x02,0xA8,0xA0,0xA8,0x10,0x97,0x03,0x90,0x00,0x14,0x00,0x12,0x00,0x06,0x20,0x95,0x03,0x31,0x01,0x95,0x03,0x12,0x20,0xC1,0x12,0xC2,0x12,0xB1,0x00,0x92,0x00,0xF0,0x00,0x31,0x01,0x95,0x03,0x01,0x02,0xBE,0x02,0xD5,0x12,0x31,0x01,0x95,0x03,0x12,0x78,0xAD,0x02,0x13,0x78,0xAD,0x03,0xE1,0x23,0x31,0x01,0x95,0x03,0x12,0x02,0x1F,0x02,0xF1,0xF2,0x31,0x01,0x95,0x03,0x12,0x02,0x1F,0x03,0xF1,0xF2,0x31,0x01,0x95,0x03,0x12,0x04,0x13,0x10,0xF1,0x23,0x31,0x01,0x95,0x03,0x12,0x05,0x13,0x10,0xF1,0x23,0xA8,0x10,0x95,0x03,0x90,0x00,0x98,0x00,0x12,0x01,0x82,0x02,0x12,0x04,0x82,0x02,0x01,0x02,0xD0,0x07,0x82,0x02,0x99,0x00,0x3A,0x02,0xA8,0x60,0x12,0xBE,0x82,0x02,0x12,0xDC,0x82,0x02,0x12,0x00,0x82,0x02,0x12,0x09,0x82,0x02,0x99,0x00,0x44,0x02,0xA8,0x80,0x11,0x01,0xD4,0x51,0x11,0x01,0xB1,0x00,0x92,0x00,0x16,0x02,0x11,0x01,0x12,0x02,0xD8,0x12,0x03,0x01,0x99,0x03,0xA8,0x10,0x99,0x03,0x12,0x40,0x82,0x02,0x12,0x40,0x82,0x02,0x03,0x02,0x99,0x03,0x82,0x02,0x99,0x00,0x4E,0x02,0xA8,0x60,0x12,0x00,0x06,0x20,0x95,0x03,0x31,0x01,0x95,0x03,0x12,0x20,0xC1,0x12,0xC2,0x12,0xB1,0x00,0x92,0x00,0xF2,0x01,0x31,0x01,0x95,0x03,0x12,0x06,0x03,0x03,0x99,0x03,0xF1,0x23,0x31,0x01,0x95,0x03,0x12,0x00,0xDC,0x12,0x12,0x02,0xC1,0x12,0xC2,0x12,0xB1,0x00,0x92,0x00,0x88,0x01,0x31,0x01,0x95,0x03,0x12,0x02,0x1F,0x02,0xF1,0xF2,0x31,0x01,0x95,0x03,0x12,0x00,0xDC,0x12,0x12,0x76,0xC1,0x12,0xC2,0x13,0xB1,0x00,0x92,0x00,0xAA,0x01,0x31,0x01,0x95,0x03,0x12,0x00,0x13,0x02,0xA2,0x23,0x1F,0x02,0xF1,0xF2,0x31,0x01,0x95,0x03,0x12,0x01,0xDC,0x12,0x12,0x02,0xC1,0x12,0xC2,0x12,0xB1,0x00,0x92,0x00,0xC8,0x01,0x31,0x01,0x95,0x03,0x12,0x02,0x1F,0x03,0xF1,0xF2,0x31,0x01,0x95,0x03,0x12,0x01,0xDC,0x12,0x12,0x76,0xC1,0x12,0xC2,0x13,0xB1,0x00,0x92,0x00,0xEA,0x01,0x31,0x01,0x95,0x03,0x12,0x00,0x13,0x02,0xA2,0x23,0x1F,0x03,0xF1,0xF2,0xA8,0x10,0x95,0x03,0x90,0x00,0x4E,0x01,0x11,0x04,0x12,0x02,0xD1,0x31,0xD1,0x42,0x01,0x02,0x84,0x03,0x82,0x02,0xD2,0x12,0x82,0x02,0x11,0x04,0x99,0x00,0x58,0x02,0x07,0x21,0xA8,0x40,0x99,0x00,0x26,0x02,0x90,0x00,0x1E,0x01,0x9A,0x00,0x01,0x0F,0x00,0x00,0x06,0xF0,0x9B,0x03,0x99,0x00,0x0A,0x00,0x50,0x00,0xC2,0x16,0xB1,0x00,0x92,0x00,0x26,0x02,0x9A,0x00,0x07,0x10,0x12,0x02,0xA0,0x12,0xD4,0x01,0x9A,0x00,0x07,0x10,0x12,0x02,0xA0,0x12,0xD7,0x01,0x9A,0x00,0x07,0x10,0x12,0x02,0xA0,0x12,0xD7,0x11,0x9A,0x00,0x07,0x10,0x12,0x02,0xA0,0x12,0xD7,0x21,0x9A,0x00,0x07,0x20,0xA0,0x21,0x02,0x22,0x20,0x32,0xB3,0x25,0x92,0x00,0x7C,0x02,0xD1,0x03,0xA8,0x02,0x20,0x32,0x91,0x00,0x60,0x02,0x9A,0x00,0xA8,0x02,0x20,0x32,0x91,0x00,0x60,0x02,0x9A,0x00,0xA8,0x02,0x20,0x32,0xB3,0x25,0x92,0x00,0xA6,0x02,0xA9,0x21,0x64,0x10,0xB3,0x44,0x92,0x00,0xAC,0x02,0xB3,0x49,0x92,0x00,0xAC,0x02,0xB3,0x53,0x92,0x00,0xB8,0x02,0xB3,0x43,0x92,0x00,0xB2,0x02,0x90,0x00,0x60,0x02,0xD1,0x03,0x90,0x00,0x72,0x02,0xD1,0x24,0x90,0x00,0x72,0x02,0xD1,0x04,0x90,0x00,0x72,0x02,0xD1,0x14,0x90,0x00,0x72,0x02,0x00,0x00,0x00,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x66,0x77,0x77,0x66,0x00,0x00,0x00,0x06,0x77,0x8F,0xC8,0x88,0x60,0x00,0x00,0x67,0x88,0x8F,0xC8,0x88,0x86,0x00,0x06,0x78,0x88,0x8F,0xC8,0x88,0x88,0x60,0x06,0x78,0x88,0x8F,0xC8,0x88,0x88,0x60,0x67,0x88,0x88,0xFC,0xCC,0x88,0x88,0xB6,0x67,0xFF,0xFF,0xCC,0xCC,0xCC,0xCC,0xB6,0x67,0xCC,0xCC,0xCC,0xCC,0xBB,0xBB,0xB6,0x67,0x88,0x88,0xCC,0xCB,0x88,0x88,0xB6,0x06,0x88,0x88,0x8C,0xB8,0x88,0x8B,0x60,0x06,0x88,0x88,0x8C,0xB8,0x88,0x8B,0x60,0x00,0x68,0x88,0x8C,0xB8,0x88,0xB6,0x00,0x00,0x06,0x88,0x8C,0xB8,0xBB,0x60,0x00,0x00,0x00,0x66,0xBB,0xBB,0x66,0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x99,0x99,0x99,0x99,0xCC,0xCB,0x9C,0xCC,0xFF,0xCB,0x9F,0xFF,0xFF,0xFB,0x9F,0xFF,0x99,0x99,0x99,0x99,0xCC,0xCC,0xCC,0xB9,0xFF,0xFF,0xFC,0xB9,0xFF,0xFF,0xFF,0xB9,0x00,0x00,0x09,0x99,0x99,0x00,0x09,0xCC,0xB9,0x00,0x09,0xFC,0xB9,0x00,0x09,0xFF,0xB9,0x00,0x99,0x99,0x99,0x99,0xCC,0xCC,0xCC,0xB9,0xFF,0xFF,0xFC,0xB9,0xFF,0xFF,0xFF,0xB9,0x00,0x00,0x20,0x4B,0x45,0x59,0x20,0x50,0x52,0x45,0x53,0x53,0x45,0x44,0x20,0x25,0x44,0x20,0x00}; +uint16_t palette[16] = { + 0x0020, 0xE718, 0xB9A8, 0x7DB6, 0x41E9, 0x6D2D, 0x21EC, 0xD5CA, + 0xAC4D, 0x31A7, 0xBB09, 0x3186, 0x73AE, 0x8D4B, 0x3DF9, 0xbdd7 +}; + +uint16_t bgr_to_rgb(uint16_t c){ + return ((c & 0x001f) << 11) + ((c & 0xf800) >> 11) + (c & 0x07e0); +} + +unsigned char hexToByte(char h){ + if(h < 48) + return 48; + if (h >= 48 && h <= 57) + h = map(h, 48, 57, 0, 9); + else if (h >= 65 && h <= 70) + h = map(h, 65, 70, 10, 15); + else if (h >= 97 && h <= 102) + h = map(h, 97, 102, 10, 15); + return h; +} + +void loadFromSerial(){ + char c; + unsigned char n; + int16_t j = 0; + for(int16_t i = 0; i < RAM_SIZE; i++) + mem[i] = 0; + while(c != '.'){ + if(Serial.available()){ + c = Serial.read(); + Serial.print(c); + if(c == '$'){ + n = 48; + while(n > 15){ + c = Serial.read(); + n = hexToByte(c); + } + Serial.print(c); + mem[j] = n << 4; + n = 48; + while(n > 15){ + c = Serial.read(); + n = hexToByte(c); + } + Serial.print(c); + mem[j] += n; + j++; + } + } + } + Serial.print(F("load ")); + Serial.print(j); + Serial.println(F(" byte")); + Serial.print(F("free heap ")); + Serial.println(system_get_free_heap_size()); + cpuInit(); +} + +void coos_cpu(void){ + while(1){ + COOS_DELAY(1); // 1 ms + timeR = millis(); + cpuOPS += 1; + cpuRun(1000); + timeCpu += millis() - timeR; + } +} + +void coos_screen(void){ + while(1){ + yield(); + COOS_DELAY(50); // 50 ms + timeR = millis(); + clearSpriteScr(); + redrawSprites(); + testSpriteCollision(); + redrawParticles(); + timeSpr += millis() - timeR; + timeR = millis(); + redrawScreen(); + setRedraw(); + timeGpu += millis() - timeR; + if(millis() - timeF > 1000){ + timeF = millis(); + fps = cadr_count; + cadr_count = cadr_count % 2; + } + } +} + +void timer_tick(void){ + for(int8_t i = 0; i < 8; i++){ + if(timers[i] >= 1) + timers[i] --; + } +} + +void coos_key(void){ + while(1){ + COOS_DELAY(100); // 100 ms + getKey(); + } +} + +void coos_info(void){ + while(1){ + COOS_DELAY(1000); // 1000 ms + voltaje = ESP.getVcc(); + tft.fillRect(0, 0, 32, 80, 0x0000); + tft.setCursor(1, 0); + tft.println("fps"); + tft.println(fps); + tft.println("cpu"); + tft.println(timeCpu, DEC); + tft.println("gpu"); + tft.println(timeGpu, DEC); + tft.println("spr"); + tft.println(timeSpr, DEC); + tft.println("kIPS"); + tft.println(cpuOPS, DEC); + timeCpu = 0; + timeGpu = 0; + timeSpr = 0; + cpuOPS = 0; + } +} + +void setup() { + byte menuSelected = 3; + // ------------------begin ESP8266'centric---------------------------------- + WiFi.forceSleepBegin(); // turn off ESP8266 RF + delay(1); // give RF section time to shutdown + system_update_cpu_freq(FREQUENCY); + // ------------------end ESP8266'centric------------------------------------ + tft.init(); // initialize LCD + tft.setRotation(1); + tft.fillScreen(0x0000); + tft.setTextSize(1); + tft.setTextColor(0xffff); + Serial.begin (115200); + Wire.begin(D2, D1); + geti2cAdress(); + Serial.println(i2c_adress, HEX); + Serial.println(); + cpuInit(); + //Initialize File System + if(SPIFFS.begin()){ + Serial.println(F("SPIFFS Initialize....ok")); + fileList("/"); + } + else{ + Serial.println(F("SPIFFS Initialization...failed")); + } + voltaje = ESP.getVcc(); + randomSeed(ESP.getVcc()); + clearScr(); + setColor(1); + randomSeed(analogRead(0)); + timer.attach(0.001, timer_tick); + coos.register_task(coos_cpu); + coos.register_task(coos_screen); + coos.register_task(coos_key); + coos.register_task(coos_info); + coos.start(); // init registered tasks +} + +void loop() { + coos.run(); // Coos scheduler + if(Serial.available()){ + char c = Serial.read(); + Serial.print(c); + if(c == 'm'){ + loadFromSerial(); + cpuInit(); + return; + } + if(c == 'r'){ + ESP.reset(); + return; + } + } +} diff --git a/README.md b/README.md index be478d5..f256331 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,7 @@ # esp8266_game_engine Used ili9341. Contains a virtual machine running games from RAM. +Used library: +[https://github.com/akouz/a_coos](https://github.com/akouz/a_coos) +[https://github.com/Bodmer/TFT_eSPI](https://github.com/Bodmer/TFT_eSPI) +Online emulator with compiler: +[https://corax89.github.io/esp8266Game/index.html](https://corax89.github.io/esp8266Game/index.html) diff --git a/cpu.ino b/cpu.ino new file mode 100644 index 0000000..3ef07fb --- /dev/null +++ b/cpu.ino @@ -0,0 +1,773 @@ +int16_t reg[15]; +int16_t pc = 0; +byte carry = 0; +byte zero = 0; +byte negative = 0; +byte redraw = 0; +int8_t color = 1; +int8_t bgcolor = 0; +String s_buffer; + +void cpuInit(){ + for(byte i = 1; i < 16; i++){ + reg[i] = 0; + } + display_init(); + reg[0] = RAM_SIZE - 1;//stack pointer + clearScr(); + color = 1; + bgcolor = 0; + setCharX(0); + setCharY(0); + pc = 0; + tft.setTextColor(palette[color]); +} +/* +void debug(){ + for(byte i = 0; i < 16; i++){ + Serial.print(" R"); + Serial.print(i); + Serial.print(':'); + Serial.print(reg[i]); + } + Serial.print(" OP:"); + Serial.print(readMem(pc),HEX); + Serial.print(" PC:"); + Serial.println(pc); + delay(10); +}*/ + +inline void writeInt(uint16_t adr, int16_t n){ + writeMem(adr + 1, (n & 0xff00) >> 8); + writeMem(adr, n & 0xff); +} + +inline int16_t readInt(uint16_t adr){ + return (readMem(adr + 1) << 8) + readMem(adr); +} + +inline void writeMem(uint16_t adr, int16_t n){ + if(adr < RAM_SIZE) + mem[adr] = n; +} + +inline byte readMem(uint16_t adr){ + return (adr < RAM_SIZE) ? mem[adr] : 0; +} + +void setRedraw(){ + redraw = 1; +} + +inline int16_t setFlags(int32_t n){ + carry = (n > 0xffff) ? 1 : 0; + zero = (n == 0) ? 1 : 0; + negative = (n < 0) ? 1 : 0; + return (int16_t)n; +} + +inline int16_t setFlagsC(int16_t n){ + carry = (n > 0xff) ? 1 : 0; + zero = (n == 0) ? 1 : 0; + negative = (n < 0) ? 1 : 0; + return (uint16_t)n; +} + +void cpuRun(uint16_t n){ + for(uint16_t i=0; i < n; i++) + cpuStep(); +} + +void cpuStep(){ + byte op1 = readMem(pc++); + byte op2 = readMem(pc++); + byte reg1 = 0; + byte reg2 = 0; + byte reg3 = 0; + uint16_t adr; + uint16_t j; + uint32_t n = 0; + //if(isDebug) + // debug(); + switch(op1 >> 4){ + case 0x0: + switch(op1){ + case 0x01: + //LDI R,int 01 0R XXXX + reg1 = (op2 & 0xf); + reg[reg1] = readInt(pc); + setFlags(reg[reg1]); + pc += 2; + break; + case 0x02: + //LDI R,(R) 02 RR + reg1 = ((op2 & 0xf0) >> 4); + reg2 = (op2 & 0xf); + reg[reg1] = readInt(reg[reg2]); + setFlags(reg[reg1]); + break; + case 0x03: + //LDI R,(adr) 03 0R XXXX + reg1 = (op2 & 0xf); + reg[reg1] = readInt(readInt(pc)); + setFlags(reg[reg1]); + pc += 2; + break; + case 0x04: + //LDI R,(int+R) 04 RR XXXX + reg1 = ((op2 & 0xf0) >> 4); + reg2 = (op2 & 0xf); + reg[reg1] = readInt(reg[reg2] + readInt(pc)); + setFlags(reg[reg1]); + pc += 2; + break; + case 0x05: + //STI (R),R 05 RR + reg1 = (op2 & 0xf0) >> 4; + reg2 = op2 & 0xf; + writeInt(reg[reg1],reg[reg2]); + break; + case 0x06: + if((op2 & 0x0f) == 0){ + //STI (adr),R 06 R0 XXXX + reg1 = (op2 & 0xf0) >> 4; + writeInt(readInt(pc),reg[reg1]); + pc += 2; + } + else{ + //STI (adr+R),R 06 RR XXXX + reg1 = (op2 & 0xf0) >> 4; + reg2 = op2 & 0xf; + writeInt(readInt(pc) + reg[reg1],reg[reg2]); + pc += 2; + } + break; + case 0x07: + //MOV R,R 07 RR + reg1 = (op2 & 0xf0) >> 4; + reg2 = op2 & 0xf; + reg[reg1] = reg[reg2]; + break; + default: + pc++; + } + break; + case 0x1: + // LDC R,char 1R XX + reg1 = (op1 & 0xf); + reg[reg1] = op2; + setFlagsC(reg[reg1]); + break; + case 0x2: + if(op1 == 0x20){ + // LDC R,(R) 20 RR + reg1 = ((op2 & 0xf0) >> 4); + reg2 = (op2 & 0xf); + reg[reg1] = readMem(reg[reg2]); + setFlagsC(reg[reg1]); + } + else{ + // LDC R,(R+R) 2R RR + reg1 = (op1 & 0xf); + reg2 = ((op2 & 0xf0) >> 4); + reg3 = (op2 & 0xf); + reg[reg1] = readMem(reg[reg2] + reg[reg3]); + setFlagsC(reg[reg1]); + } + break; + case 0x3: + switch(op1){ + case 0x30: + // LDC R,(int+R)30 RR XXXX + reg1 = ((op2 & 0xf0) >> 4); + reg2 = (op2 & 0xf); + reg[reg1] = readMem(reg[reg2] + readInt(pc)); + setFlagsC(reg[reg1]); + pc += 2; + break; + case 0x31: + // LDC R,(adr) 31 0R XXXX + reg1 = (op2 & 0xf); + reg[reg1] = readMem(readInt(pc)); + setFlagsC(reg[reg1]); + pc += 2; + break; + case 0x32: + // STC (adr),R 32 0R XXXX + reg1 = (op2 & 0xf0) >> 4; + writeMem(readInt(pc),reg[reg1]); + pc += 2; + break; + case 0x33: + // STC (int+R),R33 RR XXXX + reg1 = (op2 & 0xf0) >> 4; + reg2 = op2 & 0xf; + writeMem(readInt(pc) + reg[reg1],reg[reg2]); + pc += 2; + break; + } + break; + case 0x4: + if(op1 == 0x40){ + // STC (R),R 40 RR + reg1 = (op2 & 0xf0) >> 4; + reg2 = op2 & 0xf; + writeMem(reg[reg1], reg[reg2]); + } + else{ + // STC (R+R),R 4R RR + reg1 = (op1 & 0xf); + reg2 = ((op2 & 0xf0) >> 4); + reg3 = (op2 & 0xf); + writeMem(reg[reg1] + reg[reg2], reg[reg3]); + } + break; + case 0x5: + switch(op1){ + case 0x50: + //HLT 5000 + pc -= 2; + break; + case 0x51: + // STIMER R,R 51RR + reg1 = (op2 & 0xf0) >> 4; + reg2 = op2 & 0xf; + timers[reg[reg1] & 0x7] = reg[reg2]; + break; + case 0x52: + // GTIMER R 520R + reg1 = op2 & 0xf; + reg[reg1] = timers[reg[reg1] & 0x7]; + setFlags(reg[reg1]); + break; + } + break; + case 0x6: + // LDI R,(R+R) 6R RR + reg1 = (op1 & 0xf); + reg2 = ((op2 & 0xf0) >> 4); + reg3 = (op2 & 0xf); + reg[reg1] = readInt(reg[reg2] + reg[reg3]); + setFlags(reg[reg1]); + break; + case 0x7: + // STI (R+R),R 7R RR + reg1 = (op1 & 0xf); + reg2 = ((op2 & 0xf0) >> 4); + reg3 = (op2 & 0xf); + writeInt(reg[reg1] + reg[reg2], reg[reg3]); + break; + case 0x8: + switch(op1){ + case 0x80: + // POP R 80 0R + reg1 = (op2 & 0xf); + reg[reg1] = readInt(reg[0]); + reg[0] += 2; + break; + case 0x81: + // POPN R 81 0R + reg1 = (op2 & 0xf); + for(j = reg1; j >= 1; j--){ + reg[j] = readInt(reg[0]); + reg[0] += 2; + } + break; + case 0x82: + // PUSH R 82 0R + reg1 = (op2 & 0xf); + reg[0] -= 2; + writeInt(reg[0], reg[reg1]); + break; + case 0x83: + // PUSHN R 83 0R + reg1 = (op2 & 0xf); + for(j = 1; j <= reg1; j++){ + reg[0] -= 2; + writeInt(reg[0], reg[j]); + } + break; + } + break; + case 0x9: + switch(op1){ + case 0x90: + // JMP adr 90 00 XXXX + pc = readInt(pc); + break; + case 0x91: + // JNZ adr 91 00 XXXX + if(zero == 0) + pc = readInt(pc); + else + pc += 2; + break; + case 0x92: + // JZ adr 92 00 XXXX + if(zero != 0) + pc = readInt(pc); + else + pc += 2; + break; + case 0x93: + // JNP adr 93 00 XXXX + if(negative == 1) + pc = readInt(pc); + else + pc += 2; + break; + case 0x94: + // JP adr 94 00 XXXX + if(negative != 1) + pc = readInt(pc); + else + pc += 2; + break; + case 0x95: + // JNC adr 95 00 XXXX + if(carry != 1) + pc = readInt(pc); + else + pc += 2; + break; + case 0x96: + // JC adr 96 00 XXXX + if(carry == 1) + pc = readInt(pc); + else + pc += 2; + break; + case 0x97: + // JZR R,adr 97 0R XXXX + reg1 = op2 & 0xf; + if(reg[reg1] == 0) + pc = readInt(pc); + else + pc += 2; + break; + case 0x98: + // JNZR R,adr 98 0R XXXX + reg1 = op2 & 0xf; + if(reg[reg1] != 0) + pc = readInt(pc); + else + pc += 2; + break; + case 0x99: + // CALL adr 99 00 XXXX + reg[0] -= 2; + if(reg[0] < 0) + reg[0] += 0xffff; + writeInt(reg[0], pc + 2); + pc = readInt(pc); + break; + case 0x9A: + // RET 9A 00 + pc = readInt(reg[0]); + reg[0] += 2; + break; + } + break; + case 0xA: + switch(op1){ + case 0xA0: + // ADD R,R A0 RR + reg1 = (op2 & 0xf0) >> 4; + reg2 = op2 & 0xf; + n = reg[reg1] + reg[reg2]; + n = setFlags(n); + reg[reg1] = n; + break; + case 0xA1: + // ADC R,R A1 RR + reg1 = (op2 & 0xf0) >> 4; + reg2 = op2 & 0xf; + n = reg[reg1] + reg[reg2] + carry; + n = setFlags(n); + reg[reg1] = n; + break; + case 0xA2: + // SUB R,R A2 RR + reg1 = (op2 & 0xf0) >> 4; + reg2 = op2 & 0xf; + n = reg[reg1] - reg[reg2]; + n = setFlags(n); + reg[reg1] = n; + break; + case 0xA3: + // SBC R,R A3 RR + reg1 = (op2 & 0xf0) >> 4; + reg2 = op2 & 0xf; + n = reg[reg1] - reg[reg2] - carry; + n = setFlags(n); + reg[reg1] = n; + break; + case 0xA4: + // MUL R,R A4 RR + reg1 = (op2 & 0xf0) >> 4; + reg2 = op2 & 0xf; + n = reg[reg1] * reg[reg2]; + n = setFlags(n); + reg[reg1] = n; + break; + case 0xA5: + // DIV R,R A5 RR + reg1 = (op2 & 0xf0) >> 4; + reg2 = op2 & 0xf; + if(reg[reg2] != 0) + n = reg[reg1] / reg[reg2]; + else + n = 0;//error + n = setFlags(n); + reg[reg2] = reg[reg1] % reg[reg2]; + reg[reg1] = n; + break; + case 0xA6: + // AND R,R A6 RR + reg1 = (op2 & 0xf0) >> 4; + reg2 = op2 & 0xf; + n = reg[reg1] & reg[reg2]; + n = setFlags(n); + reg[reg1] = n; + break; + case 0xA7: + // OR R,R A7 RR + reg1 = (op2 & 0xf0) >> 4; + reg2 = op2 & 0xf; + n = reg[reg1] | reg[reg2]; + n = setFlags(n); + reg[reg1] = n; + break; + case 0xA8: + if(op2 == 0x10){ + // INC adr A8 10 XXXX + reg1 = op2 & 0xf; + n = readInt(readInt(pc)) + 1; + n = setFlags(n); + writeInt(readInt(pc), n); + pc += 2; + } + else if(op2 > 0x10){ + // INC R,n A8 nR + reg1 = op2 & 0xf; + n = reg[reg1] + (op2 >> 4); + n = setFlags(n); + reg[reg1] = n; + } + else{ + // INC R A8 0R + reg1 = op2 & 0xf; + n = reg[reg1] + 1; + n = setFlags(n); + reg[reg1] = n; + } + break; + case 0xA9: + if(op2 == 0x10){ + // DEC adr A9 10 XXXX + reg1 = op2 & 0xf; + n = readInt(readInt(pc)) - 1; + n = setFlags(n); + writeInt(readInt(pc), n); + pc += 2; + } + else if(op2 > 0x10){ + // DEC R,n A9 nR + reg1 = op2 & 0xf; + n = reg[reg1] - (op2 >> 4); + n = setFlags(n); + reg[reg1] = n; + } + else{ + // DEC R A9 0R + reg1 = op2 & 0xf; + n = reg[reg1] - 1; + n = setFlags(n); + reg[reg1] = n; + } + break; + case 0xAA: + // XOR R,R AA RR + reg1 = (op2 & 0xf0) >> 4; + reg2 = op2 & 0xf; + n = reg[reg1] ^ reg[reg2]; + n = setFlags(n); + reg[reg1] = n; + break; + case 0xAB: + // SHL R,R AB RR + reg1 = (op2 & 0xf0) >> 4; + reg2 = op2 & 0xf; + n = reg[reg1] << reg[reg2]; + n = setFlags(n); + reg[reg1] = n; + break; + case 0xAC: + // SHR R,R AC RR + reg1 = (op2 & 0xf0) >> 4; + reg2 = op2 & 0xf; + n = reg[reg1] >> reg[reg2]; + n = setFlags(n); + reg[reg1] = n; + break; + case 0xAD: + // RAND R,R AD 0R + reg1 = op2 & 0xf; + n = random(0, reg[reg1] + 1); + n = setFlags(n); + reg[reg1] = n; + break; + } + break; + case 0xB: + //CMP R,CHR BR XX + reg1 = (op1 & 0x0f); + n = reg[reg1] - op2; + n = setFlags(n); + break; + case 0xC: + switch(op1){ + case 0xC0: + //CMP R,INT C0 R0 XXXX + reg1 = (op2 & 0xf0) >> 4; + n = reg[reg1] - readInt(pc); + n = setFlags(n); + pc += 2; + break; + case 0xC1: + //CMP R,R C1 RR + reg1 = (op2 & 0xf0) >> 4; + reg2 = op2 & 0xf; + n = reg[reg1] - reg[reg2]; + n = setFlags(n); + break; + case 0xC2: + //LDF R,F C2 RF + reg1 = (op2 & 0xf0) >> 4; + reg2 = op2 & 0xf; + if(reg2 == 0) + reg[reg1] = carry; + else if(reg2 == 1) + reg[reg1] = zero; + else if(reg2 == 2) + reg[reg1] = negative; + else if(reg2 == 3){ //pozitive + if(negative == 0 && zero == 0) + reg[reg1] = 1; + else + reg[reg1] = 0; + } + else if(reg2 == 4){ //not pozitive + if(negative == 0 && zero == 0) + reg[reg1] = 0; + else + reg[reg1] = 1; + } + else if(reg2 == 5) + reg[reg1] = 1 - zero; + else if(reg2 == 6){ + reg[reg1] = redraw; + redraw = 0; + } + else + reg[reg1] = 0; + break; + } + break; + case 0xD: + switch(op1){ + case 0xD0: + //CLS D000 + clearScr(); + break; + case 0xD1: + switch(op2 & 0xf0){ + case 0x00: + //PUTC R D10R + reg1 = (op2 & 0xf); + printc((char)reg[reg1], color, bgcolor); + break; + case 0x10: + //PUTS R D11R + reg1 = (op2 & 0xf); + j = 0; + while(!(readMem(reg[reg1] + j) == 0 || j > 1000)){ + printc((char)(readMem(reg[reg1] + j)), color, bgcolor); + j++; + } + break; + case 0x20: + //PUTN R D12R + reg1 = (op2 & 0xf); + if(reg[reg1] < 32768) + s_buffer = String(reg[reg1]); + else + s_buffer = String(reg[reg1] - 0x10000); + for(j = 0; j < s_buffer.length(); j++){ + printc(s_buffer[j], color, bgcolor); + } + break; + case 0x30: + //SETX R D13R + reg1 = (op2 & 0xf); + setCharX(reg[reg1] & 0xff); + break; + case 0x40: + //SETY R D14R + reg1 = (op2 & 0xf); + setCharY(reg[reg1] & 0xff); + break; + } + break; + case 0xD2: + switch(op2 & 0xf0){ + case 0x00: + // GETK R D20R + reg1 = (op2 & 0xf); + if(Serial.available()) + reg[reg1] = Serial.read(); + else + pc -= 2; + break; + case 0x10: + // GETJ R D21R + reg1 = (op2 & 0xf); + reg[reg1] = thiskey; + break; + } + break; + case 0xD3: + // PPIX R,R D3RR + reg1 = (op2 & 0xf0) >> 4; + reg2 = op2 & 0xf; + setPix(reg[reg1], reg[reg2], color); + break; + case 0xD4: + switch(op2 & 0xf0){ + case 0x00: + // DRWIM R D40R + reg1 = op2 & 0xf; + adr = reg[reg1];//регистр указывает на участок памяти, в котором расположены последовательно h, w, y, x, адрес + drawImg(readInt(adr + 8), readInt(adr + 6), readInt(adr + 4), readInt(adr + 2), readInt(adr)); + break; + case 0x10: + // SFCLR R D41R + reg1 = op2 & 0xf; + color = reg[reg1] & 0xf; + break; + case 0x20: + // SBCLR R D42R + reg1 = op2 & 0xf; + bgcolor = reg[reg1] & 0xf; + break; + case 0x30: + // GFCLR R D43R + reg1 = op2 & 0xf; + reg[reg1] = color; + break; + case 0x40: + // GBCLR R D44R + reg1 = op2 & 0xf; + reg[reg1] = bgcolor; + break; + case 0x50: + // ISIZE D45R + reg1 = op2 & 0xf; + setImageSize(reg[reg1] & 31); + break; + case 0x60: + // DLINE D46R + reg1 = op2 & 0xf; + adr = reg[reg1];//регистр указывает на участок памяти, в котором расположены последовательно y1, x1, y, x + drwLine(readInt(adr + 6), readInt(adr + 4), readInt(adr + 2), readInt(adr)); + break; + case 0x070: + // // DRWRLE R D47R + reg1 = op2 & 0xf; + adr = reg[reg1];//регистр указывает на участок памяти, в котором расположены последовательно h, w, y, x, адрес + drawImgRLE(readInt(adr + 8), readInt(adr + 6), readInt(adr + 4), readInt(adr + 2), readInt(adr)); + break; + case 0x80: + // LDTILE R D4 8R + reg1 = op2 & 0xf; + adr = reg[reg1];//регистр указывает на участок памяти, в котором расположены последовательно height, width, iheight, iwidth, adr + loadTile(readInt(adr + 8), readInt(adr + 6), readInt(adr + 4), readInt(adr + 2), readInt(adr)); + break; + } + break; + case 0xD5: + // LDSPRT R,R D5RR + reg1 = (op2 & 0xf0) >> 4;//номер спрайта + reg2 = op2 & 0xf;//адрес спрайта + setSpr(reg[reg1] & 0x1f, reg[reg2]); + break; + case 0xD6: + // SPALET R,R D6 RR + reg1 = (op2 & 0xf0) >> 4;//номер спрайта + reg2 = op2 & 0xf;//width + changePalette(reg[reg1] & 15, reg[reg2]); + break; + case 0xD7: + reg1 = op2 & 0xf; + adr = reg[reg1]; + // SPART R D7 0R + if((op2 & 0xf0) == 0x0) + //регистр указывает на участок памяти, в котором расположены последовательно count, time, gravity + setParticle(readInt(adr + 4), readInt(adr + 2), readInt(adr)); + else if((op2 & 0xf0) == 0x10) + //регистр указывает на участок памяти, в котором расположены последовательно speed, direction2, direction1, time + setEmitter(readInt(adr + 6), readInt(adr + 4), readInt(adr + 2), readInt(adr)); + else if((op2 & 0xf0) == 0x20) + //регистр указывает на участок памяти, в котором расположены последовательно color, y, x + drawParticle(readInt(adr + 4), readInt(adr + 2), readInt(adr) & 0xf); + break; + case 0xD8: + // SCROLL R,R D8RR + reg1 = (op2 & 0xf0) >> 4;//шаг + reg2 = op2 & 0xf;//направление + scrollScreen(reg[reg1], reg[reg2]); + break; + case 0xD9: + // GETPIX R,R D9RR + reg1 = (op2 & 0xf0) >> 4;//x + reg2 = op2 & 0xf;//y + reg[reg1] = getPix(reg[reg1], reg[reg2]); + break; + case 0xDA: + // DRTILE R DA RR + reg1 = (op2 & 0xf0) >> 4;//x + reg2 = op2 & 0xf;//y + drawTile(reg[reg1], reg[reg2]); + break; + case 0xDB: + // SPRSPX R,R DB RR + reg1 = (op2 & 0xf0) >> 4;//num + reg2 = op2 & 0xf;//speed y + + break; + case 0xDC: + // SPRGTX R,X DC RX + reg1 = (op2 & 0xf0) >> 4;//num + reg2 = op2 & 0xf;//value + reg[reg1] = getSpriteValue(reg[reg1] & 31, reg[reg2]); + break; + } + break; + case 0xE: + // DRSPRT R,R,R ERRR + reg1 = (op1 & 0xf);//номер спрайта + reg2 = (op2 & 0xf0) >> 4;//x + reg3 = op2 & 0xf;//y + setSprPosition(reg[reg1] & 0x1f, reg[reg2], reg[reg3]); + if(getSpriteValue(reg[reg1] & 0x1f, 7) < 1) + setSpriteValue(reg[reg1] & 0x1f, 7, 1); + break; + case 0xF: + // SSPRTV R,R,R FR RR + reg1 = (op1 & 0xf);//номер спрайта + reg2 = (op2 & 0xf0) >> 4;//type + reg3 = op2 & 0xf;//value + setSpriteValue(reg[reg1] & 0x1f, reg[reg2], reg[reg3]); + break; + } +} diff --git a/data/collision.bin b/data/collision.bin new file mode 100644 index 0000000..7c1b05a Binary files /dev/null and b/data/collision.bin differ diff --git a/data/pi.bin b/data/pi.bin new file mode 100644 index 0000000..f561aa4 Binary files /dev/null and b/data/pi.bin differ diff --git a/data/platformer.bin b/data/platformer.bin new file mode 100644 index 0000000..919f588 Binary files /dev/null and b/data/platformer.bin differ diff --git a/data/snake.bin b/data/snake.bin new file mode 100644 index 0000000..e302c66 Binary files /dev/null and b/data/snake.bin differ diff --git a/data/space.bin b/data/space.bin new file mode 100644 index 0000000..66a46e2 Binary files /dev/null and b/data/space.bin differ diff --git a/display.ino b/display.ino new file mode 100644 index 0000000..85950c5 --- /dev/null +++ b/display.ino @@ -0,0 +1,1063 @@ +#include "font_a.c" + +#define PARTICLE_COUNT 32 + +struct sprite { + int16_t address; + int16_t x; + int16_t y; + uint8_t width; + uint8_t height; + int8_t speedx; + int8_t speedy; + int16_t angle; + int8_t lives; + int8_t collision; + uint8_t solid; + int8_t gravity; +}; + +struct Particle { + int16_t time; + int16_t x; + int16_t y; + int8_t gravity; + int8_t speedx; + int8_t speedy; + int8_t color; +}; + +struct Emitter { + int16_t time; + int16_t timer; + int16_t timeparticle; + uint8_t count; + int8_t gravity; + int16_t x; + int16_t y; + int8_t speedx; + int8_t speedy; + int8_t speedx1; + int8_t speedy1; + int8_t color; +}; + +struct Tile { + int16_t adr; + uint8_t imgwidth; + uint8_t imgheight; + uint8_t width; + uint8_t height; + int16_t x; + int16_t y; +}; + +static const int8_t cosT[] PROGMEM = { + 0x40, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3e, 0x3e, 0x3e, 0x3e, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c, + 0x3c, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39, 0x39, 0x38, 0x37, 0x37, 0x36, 0x36, 0x35, 0x35, 0x34, 0x33, 0x33, 0x32, 0x31, + 0x31, 0x30, 0x2f, 0x2e, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, + 0x20, 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0xf, 0xe, 0xd, 0xc, 0xb, + 0xa, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf7, 0xf5, 0xf4, 0xf3, 0xf2, + 0xf1, 0xf0, 0xef, 0xee, 0xed, 0xec, 0xeb, 0xea, 0xe9, 0xe8, 0xe6, 0xe5, 0xe4, 0xe3, 0xe2, 0xe1, 0xe0, 0xe0, 0xdf, 0xde, + 0xdd, 0xdc, 0xdb, 0xda, 0xd9, 0xd8, 0xd7, 0xd6, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xd1, 0xd0, 0xcf, 0xce, 0xce, 0xcd, + 0xcc, 0xcc, 0xcb, 0xca, 0xca, 0xc9, 0xc9, 0xc8, 0xc8, 0xc7, 0xc6, 0xc6, 0xc5, 0xc5, 0xc5, 0xc4, 0xc4, 0xc3, 0xc3, 0xc3, + 0xc2, 0xc2, 0xc2, 0xc1, 0xc1, 0xc1, 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, + 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc1, 0xc1, 0xc1, 0xc2, 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, + 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc8, 0xc8, 0xc9, 0xc9, 0xca, 0xca, 0xcb, 0xcc, 0xcc, 0xcd, 0xce, 0xce, 0xcf, 0xd0, + 0xd1, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xdf, 0xe0, 0xe1, + 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x1f, 0x20, 0x21, 0x22, 0x23, + 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2e, 0x2f, 0x30, 0x31, 0x31, 0x32, 0x33, 0x33, + 0x34, 0x35, 0x35, 0x36, 0x36, 0x37, 0x37, 0x38, 0x39, 0x39, 0x3a, 0x3a, 0x3a, 0x3b, 0x3b, 0x3c, 0x3c, 0x3c, 0x3d, 0x3d, + 0x3d, 0x3e, 0x3e, 0x3e, 0x3e, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f +}; +static const int8_t sinT[] PROGMEM = { + 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x29, 0x2a, + 0x2b, 0x2c, 0x2d, 0x2e, 0x2e, 0x2f, 0x30, 0x31, 0x31, 0x32, 0x33, 0x33, 0x34, 0x35, 0x35, 0x36, 0x36, 0x37, 0x37, 0x38, + 0x39, 0x39, 0x3a, 0x3a, 0x3a, 0x3b, 0x3b, 0x3c, 0x3c, 0x3c, 0x3d, 0x3d, 0x3d, 0x3e, 0x3e, 0x3e, 0x3e, 0x3f, 0x3f, 0x3f, + 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3e, 0x3e, + 0x3e, 0x3e, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c, 0x3c, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39, 0x39, 0x38, 0x37, 0x37, 0x36, 0x36, + 0x35, 0x35, 0x34, 0x33, 0x33, 0x32, 0x31, 0x31, 0x30, 0x2f, 0x2e, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x29, 0x28, 0x27, + 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x20, 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x17, 0x16, 0x15, 0x14, 0x13, + 0x12, 0x11, 0x10, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, + 0xf9, 0xf8, 0xf7, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, 0xef, 0xee, 0xed, 0xec, 0xeb, 0xea, 0xe9, 0xe8, 0xe6, 0xe5, 0xe4, + 0xe3, 0xe2, 0xe1, 0xe0, 0xe0, 0xdf, 0xde, 0xdd, 0xdc, 0xdb, 0xda, 0xd9, 0xd8, 0xd7, 0xd6, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, + 0xd1, 0xd1, 0xd0, 0xcf, 0xce, 0xce, 0xcd, 0xcc, 0xcc, 0xcb, 0xca, 0xca, 0xc9, 0xc9, 0xc8, 0xc8, 0xc7, 0xc6, 0xc6, 0xc5, + 0xc5, 0xc5, 0xc4, 0xc4, 0xc3, 0xc3, 0xc3, 0xc2, 0xc2, 0xc2, 0xc1, 0xc1, 0xc1, 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, + 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc1, 0xc1, 0xc1, 0xc2, + 0xc2, 0xc2, 0xc3, 0xc3, 0xc3, 0xc4, 0xc4, 0xc5, 0xc5, 0xc5, 0xc6, 0xc6, 0xc7, 0xc8, 0xc8, 0xc9, 0xc9, 0xca, 0xca, 0xcb, + 0xcc, 0xcc, 0xcd, 0xce, 0xce, 0xcf, 0xd0, 0xd1, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, + 0xdc, 0xdd, 0xde, 0xdf, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe +}; + +uint8_t screen[64][128]; +uint8_t line_is_draw[128]; +uint8_t sprite_screen[64][128]; +char charArray[340]; +uint16_t pix_buffer[256]; +struct sprite sprite_table[32]; +struct Particle particles[PARTICLE_COUNT]; +struct Emitter emitter; +struct Tile tile; +int8_t imageSize = 1; +int8_t regx = 0; +int8_t regy = 0; + +int16_t getCos(int16_t g){ + if(g >= 360) + g = g % 360; + return (int16_t)(int8_t)pgm_read_byte_near(cosT + g); +} + +int16_t getSin(int16_t g){ + if(g >= 360) + g = g % 360; + return (int16_t)(int8_t)pgm_read_byte_near(sinT + g); +} + +void display_init(){ + for(byte i = 0; i < 32; i++){ + sprite_table[i].address = 0; + sprite_table[i].x = -255; + sprite_table[i].y = -255; + sprite_table[i].width = 8; + sprite_table[i].height = 8; + sprite_table[i].speedx = 0; + sprite_table[i].speedy = 0; + sprite_table[i].angle = 0; + sprite_table[i].lives = 0; + sprite_table[i].collision = -1; + sprite_table[i].solid = 0; + sprite_table[i].gravity = 0; + } + emitter.time = 0; + emitter.timer = 0; + tile.adr = 0; + for(byte i = 0; i < PARTICLE_COUNT; i++) + particles[i].time = 0; + for(uint16_t i = 0; i < 340; i++) + charArray[i] = 0; + imageSize = 1; + regx = 0; + regy = 0; +} + +int8_t randomD(int8_t a, int8_t b) { + int8_t minv = a < b ? a : b; + int8_t maxv = a > b ? a : b; + return random(minv, maxv + 1); +} + +void setParticle(int8_t gravity, uint8_t count, uint16_t time){ + emitter.gravity = gravity; + emitter.count = count; + emitter.timeparticle = time; +} + +void setEmitter(uint16_t time, int16_t dir, int16_t dir1, int16_t speed){ + emitter.time = time; + emitter.speedx = (int8_t)((speed * getCos(dir)) >> 6); + emitter.speedy = (int8_t)((speed * getSin(dir)) >> 6); + emitter.speedx1 = (int8_t)((speed * getCos(dir1)) >> 6); + emitter.speedy1 = (int8_t)((speed * getSin(dir1)) >> 6); +} + +void drawParticle(int16_t x, int16_t y, uint8_t color){ + emitter.x = x; + emitter.y = y; + emitter.color = color; + emitter.timer = emitter.time; +} + +void redrawScreen(){ + uint8_t i; + cadr_count++; + for(uint8_t y = 0; y < 128; y++){ + i = 0; + if(line_is_draw[y] == 1){ + if(y < 8) + tft.setAddrWindow(32 + 0, y, 32 + 127, y + 1); + else if(y > 120) + tft.setAddrWindow(32 + 0, 232 - 120 + y, 32 + 127, 232 - 120 + y + 1); + else + tft.setAddrWindow(32 + 0, y * 2 - 8, 32 + 127, y * 2 + 2 - 8); + //в одной ячейке памяти содержится два пикселя + for(uint8_t x = 0; x < 32; x++){ + if((sprite_screen[x][y] & 0xf0) > 0) + pix_buffer[i] = palette[(sprite_screen[x][y] & 0xf0) >> 4]; + else + pix_buffer[i] = palette[(screen[x][y] & 0xf0) >> 4]; + i++; + pix_buffer[i] = pix_buffer[i - 1]; + i++; + if((sprite_screen[x][y] & 0x0f) > 0) + pix_buffer[i] = palette[sprite_screen[x][y] & 0x0f]; + else + pix_buffer[i] = palette[screen[x][y] & 0x0f]; + i++; + pix_buffer[i] = pix_buffer[i - 1]; + i++; + } + tft.pushColors(pix_buffer, 128); + if(y >= 8 && y <= 120) + tft.pushColors(pix_buffer, 128); + line_is_draw[y] = 0; + } + else if(line_is_draw[y] == 2){ + if(y < 8) + tft.setAddrWindow(32 + 128, y, 32 + 255, y + 1); + else if(y > 120) + tft.setAddrWindow(32 + 128, 232 - 120 + y, 32 + 255, 232 - 120 + y + 1); + else + tft.setAddrWindow(32 + 128, y * 2 - 8, 32 + 255, y * 2 + 2 - 8); + //в одной ячейке памяти содержится два пикселя + for(uint8_t x = 0; x < 32; x++){ + if((sprite_screen[x + 32][y] & 0xf0) > 0) + pix_buffer[i] = palette[(sprite_screen[x + 32][y] & 0xf0) >> 4]; + else + pix_buffer[i] = palette[(screen[x + 32][y] & 0xf0) >> 4]; + i++; + pix_buffer[i] = pix_buffer[i - 1]; + i++; + if((sprite_screen[x + 32][y] & 0x0f) > 0) + pix_buffer[i] = palette[sprite_screen[x + 32][y] & 0x0f]; + else + pix_buffer[i] = palette[screen[x + 32][y] & 0x0f]; + i++; + pix_buffer[i] = pix_buffer[i - 1]; + i++; + } + tft.pushColors(pix_buffer, 128); + if(y >= 8 && y <= 120) + tft.pushColors(pix_buffer, 128); + line_is_draw[y] = 0; + } + else if(line_is_draw[y] == 3){ + if(y < 8) + tft.setAddrWindow(32 + 0, y, 32 + 255, y + 1); + else if(y > 120) + tft.setAddrWindow(32 + 0, 232 - 120 + y, 32 + 255, 232 - 120 + y + 1); + else + tft.setAddrWindow(32 + 0, y * 2 - 8, 32 + 255, y * 2 + 2 - 8); + //в одной ячейке памяти содержится два пикселя + for(uint8_t x = 0; x < 64; x++){ + if((sprite_screen[x][y] & 0xf0) > 0) + pix_buffer[i] = palette[(sprite_screen[x][y] & 0xf0) >> 4]; + else + pix_buffer[i] = palette[(screen[x][y] & 0xf0) >> 4]; + i++; + pix_buffer[i] = pix_buffer[i - 1]; + i++; + if((sprite_screen[x][y] & 0x0f) > 0) + pix_buffer[i] = palette[sprite_screen[x][y] & 0x0f]; + else + pix_buffer[i] = palette[screen[x][y] & 0x0f]; + i++; + pix_buffer[i] = pix_buffer[i - 1]; + i++; + } + tft.pushColors(pix_buffer, 256); + if(y >= 8 && y <= 120) + tft.pushColors(pix_buffer, 256); + line_is_draw[y] = 0; + } + } +} + +void redrawParticles(){ + int16_t i, n; + uint8_t x, y; + if(emitter.timer > 0){ + emitter.timer -= 50; + i = emitter.count; + for(n = 0; n < PARTICLE_COUNT; n++){ + if(i == 0) + break; + if(particles[n].time <= 0){ + i--; + particles[n].time = emitter.timeparticle; + particles[n].x = emitter.x; + particles[n].y = emitter.y; + particles[n].color = emitter.color; + particles[n].speedx = randomD(emitter.speedx, emitter.speedx1); + particles[n].speedy = randomD(emitter.speedy, emitter.speedy1); + particles[n].gravity = emitter.gravity; + } + } + } + for(n = 0; n < PARTICLE_COUNT; n++) + if(particles[n].time > 0){ + x = (particles[n].x & 127) / 2; + y = particles[n].y & 127; + if(particles[n].x & 1) + sprite_screen[x][y] = (sprite_screen[x][y] & 0xf0) + (particles[n].color & 0x0f); + else + sprite_screen[x][y] = (sprite_screen[x][y] & 0x0f) + ((particles[n].color & 0x0f) << 4); + line_is_draw[y] |= 1 + x / 32; + particles[n].time -= 50; + if(random(0,2)){ + particles[n].x += particles[n].speedx; + particles[n].speedy += particles[n].gravity; + particles[n].y += particles[n].speedy; + } + else{ + particles[n].x += particles[n].speedx / 2; + particles[n].y += particles[n].speedy / 2; + } + if(particles[n].x < 0 || particles[n].x > 128 || particles[n].y < 0 || particles[n].y > 128) + particles[n].time = 0; + } +} + +void redrawSprites(){ + for(byte i = 0; i < 32; i++){ + if(sprite_table[i].lives > 0) + if(sprite_table[i].x < 128 && sprite_table[i].y < 128) + drawSpr(i, sprite_table[i].x, sprite_table[i].y); + sprite_table[i].speedy += sprite_table[i].gravity; + sprite_table[i].x += sprite_table[i].speedx; + sprite_table[i].y += sprite_table[i].speedy; + } +} + +uint16_t getTail(int16_t x, int16_t y){ + if(x < 0 || x >= tile.width || y < 0 || y >= tile.height) + return 0; + return readInt(tile.adr + (x + y * tile.width) * 2); +} + +void testSpriteCollision(){ + byte n, i; + int16_t x0, y0, newspeed; + //int16_t adr; + for(n = 0; n < 32; n++) + sprite_table[n].collision = -1; + for(n = 0; n < 32; n++){ + if(sprite_table[n].lives > 0){ + for(i = 0; i < n; i++){ + if(sprite_table[i].lives > 0){ + if(sprite_table[n].x < sprite_table[i].x + sprite_table[i].width && + sprite_table[n].x + sprite_table[n].width > sprite_table[i].x && + sprite_table[n].y < sprite_table[i].y + sprite_table[i].height && + sprite_table[n].y + sprite_table[n].height > sprite_table[i].y){ + sprite_table[n].collision = i; + sprite_table[i].collision = n; + if(sprite_table[n].solid != 0 && sprite_table[i].solid != 0){ + if((sprite_table[n].speedx > 0 && sprite_table[i].speedx < 0) || (sprite_table[n].speedx < 0 && sprite_table[i].speedx > 0)){ + newspeed = (abs(sprite_table[n].speedx) + abs(sprite_table[i].speedx)) / 2; + if(sprite_table[n].x > sprite_table[i].x){ + sprite_table[n].speedx = newspeed; + sprite_table[i].speedx = -newspeed; + } + else{ + sprite_table[n].speedx = -newspeed; + sprite_table[i].speedx = newspeed; + } + sprite_table[n].x -= 2; + } + if((sprite_table[n].speedy > 0 && sprite_table[i].speedy < 0) || (sprite_table[n].speedy < 0 && sprite_table[i].speedy > 0)){ + newspeed = (abs(sprite_table[n].speedy) + abs(sprite_table[i].speedy)) / 2; + if(sprite_table[n].y > sprite_table[i].y){ + sprite_table[n].speedy = newspeed; + sprite_table[i].speedy = -newspeed; + } + else{ + sprite_table[n].speedy = -newspeed; + sprite_table[i].speedy = newspeed; + } + sprite_table[n].y -= 2; + } + } + } + } + } + if(sprite_table[n].solid != 0 && tile.adr > 0){ + x0 = ((sprite_table[n].x + sprite_table[n].width / 2 - tile.x) / (int16_t)tile.imgwidth); + y0 = ((sprite_table[n].y + sprite_table[n].height / 2 - tile.y + tile.imgheight) / (int16_t)tile.imgheight) - 1; + if(x0 >= -1 && x0 <= tile.width && y0 >= -1 && y0 <= tile.height){ + if(getTail(x0, y0) != 0){ + if(sprite_table[n].speedx != 0){ + if(sprite_table[n].speedx > 0){ + sprite_table[n].x = tile.x + x0 * tile.imgwidth - sprite_table[n].width ; + sprite_table[n].speedx /= 2; + } + else{ + sprite_table[n].x = tile.x + (x0 + 1) * tile.imgwidth; + sprite_table[n].speedx /= 2; + } + } + if(sprite_table[n].speedy != 0){ + if(sprite_table[n].speedy > 0){ + sprite_table[n].y = tile.y + y0 * tile.imgheight - sprite_table[n].height ; + sprite_table[n].speedy /= 2; + } + else{ + sprite_table[n].y = tile.y + (y0 + 1) * tile.imgheight; + sprite_table[n].speedy /= 2; + } + } + } + else{ + if(sprite_table[n].speedy > 0 && getTail(x0, y0 + 1) != 0){ + if((tile.y + (y0 + 1) * tile.imgheight) - (sprite_table[n].y + sprite_table[n].height) < sprite_table[n].speedy * 2){ + sprite_table[n].y = tile.y + (y0 + 1) * tile.imgheight - sprite_table[n].height; + sprite_table[n].speedy = 0; + } + } + else if(sprite_table[n].speedy < 0 && getTail(x0, y0 - 1) != 0){ + if(sprite_table[n].y - (tile.y + y0 * tile.imgheight) < sprite_table[n].speedy * 2){ + sprite_table[n].y = tile.y + y0 * tile.imgheight; + sprite_table[n].speedy = 0; + } + } + if(sprite_table[n].speedx > 0 && getTail(x0 + 1, y0) != 0){ + if((tile.x + (x0 + 1) * tile.imgwidth - sprite_table[n].width) - sprite_table[n].x < sprite_table[n].speedx * 2){ + sprite_table[n].x = tile.x + (x0 + 1) * tile.imgwidth - sprite_table[n].width; + sprite_table[n].speedx = 0; + } + } + else if(sprite_table[n].speedx < 0 && getTail(x0 - 1, y0) != 0){ + if(sprite_table[n].x - (tile.x + x0 * tile.imgwidth) < sprite_table[n].speedx * 2){ + sprite_table[n].x = tile.x + x0 * tile.imgwidth; + sprite_table[n].speedx = 0; + } + } + } + } + } + + } + } +} + +void clearSpriteScr(){ + for(byte y = 0; y < 128; y ++) + for(byte x = 0; x < 64; x++){ + if(sprite_screen[x][y] > 0) + line_is_draw[y] |= 1 + x / 32; + sprite_screen[x][y] = 0; + } +} + +void clearScr(){ + for(byte y = 0; y < 128; y ++){ + line_is_draw[y] = 3; + for(byte x = 0; x < 64; x++) + screen[x][y] = 0; + } +} + +void setImageSize(uint8_t size){ + imageSize = size; +} + +void setSpr(uint16_t n, uint16_t adr){ + sprite_table[n].address = adr; +} + +void setSprPosition(int8_t n, uint16_t x, uint16_t y){ + sprite_table[n].x = x; + sprite_table[n].y = y; +} + +void setSprWidth(int8_t n, uint8_t w){ + sprite_table[n].width = w; +} + +void setSprHeight(int8_t n, uint8_t w){ + sprite_table[n].height = w; +} + +void setSprSpeedx(int8_t n, int8_t s){ + sprite_table[n].speedx = s; +} + +void setSprSpeedy(int8_t n, int8_t s){ + sprite_table[n].speedy = s; +} + +int16_t getSpriteValue(int8_t n, uint8_t t){ + if(t == 0) + return sprite_table[n].x; + else if(t == 1) + return sprite_table[n].y; + else if(t == 2) + return sprite_table[n].speedx; + else if(t == 3) + return sprite_table[n].speedy; + else if(t == 4) + return sprite_table[n].width; + else if(t == 5) + return sprite_table[n].height; + else if(t == 6) + return sprite_table[n].angle; + else if(t == 7) + return sprite_table[n].lives; + else if(t == 8) + return sprite_table[n].collision; + else if(t == 9) + return sprite_table[n].solid; + else if(t == 10) + return sprite_table[n].gravity; + return 0; +} + +void setSpriteValue(int8_t n, uint8_t t, int16_t v){ + if(t == 0) + sprite_table[n].x = v; + else if(t == 1) + sprite_table[n].y = v; + else if(t == 2){ + sprite_table[n].speedx = (int8_t) v; + } + else if(t == 3){ + sprite_table[n].speedy = (int8_t) v; + } + else if(t == 4) + sprite_table[n].width = v; + else if(t == 5) + sprite_table[n].height = v; + else if(t == 6) + sprite_table[n].angle = (v % 360) & 0x01ff; + else if(t == 7) + sprite_table[n].lives = v; + else if(t == 9) + sprite_table[n].solid = v; + else if(t == 10) + sprite_table[n].gravity = v; +} + +void drawRotateSprPixel(int8_t pixel, int8_t x0, int8_t y0, int16_t x, int16_t y, int16_t hw, int16_t hh, int16_t c, int16_t s){ + //int16_t nx = ((x * c - y * s) >> 6); + //int16_t ny = ((y * c + x * s) >> 6); + int16_t nx = hw + (((x - hw) * c - (y - hh) * s) >> 6); + int16_t ny = hh + (((y - hh) * c + (x - hw) * s) >> 6); + int16_t nnx = nx / 2; + x0 = x0/2; + if(x0 + nnx >= 0 && x0 + nnx < 64 && y0 + ny >= 0 && y0 + ny < 128){ + if(nx & 1) + sprite_screen[x0 + nnx][y0 + ny] = (sprite_screen[x0 + nnx][y0 + ny] & 0xf0) + pixel; + else + sprite_screen[x0 + nnx][y0 + ny] = (sprite_screen[x0 + nnx][y0 + ny] & 0x0f) + (pixel << 4); + line_is_draw[y0 + ny] |= 1 + (x0 + nnx) / 32; + } +} + +inline void drawSprPixel(int8_t pixel, int8_t x0, int8_t y0, int16_t x, int16_t y){ + if(x0 + x >= 0 && x0 + x < 128 && y0 + y >= 0 && y0 + y < 128){ + if(x & 1) + sprite_screen[(x0 + x) / 2][y0 + y] = (sprite_screen[(x0 + x) / 2][y0 + y] & 0xf0) + pixel; + else + sprite_screen[(x0 + x) / 2][y0 + y] = (sprite_screen[(x0 + x) / 2][y0 + y] & 0x0f) + (pixel << 4); + line_is_draw[y0 + y] |= 1 + (x0 + x) / 64; + } +} + +void drawSpr(int8_t n, uint16_t x, uint16_t y){ + uint16_t adr = sprite_table[n].address; + uint8_t w = sprite_table[n].width; + uint8_t h = sprite_table[n].height; + int16_t c = getCos(sprite_table[n].angle); + int16_t s = getSin(sprite_table[n].angle); + uint8_t pixel; + w = w / 2; + if(sprite_table[n].angle == 0){ + for(byte y1 = 0; y1 < h; y1 ++) + if(y1 + y >= -h && y1 + y < 128 + h){ + for(byte x1 = 0; x1 < w; x1++){ + pixel = readMem(adr + x1 + y1 * w); + if((pixel & 0xf0) > 0) + drawSprPixel(pixel >> 4, x, y, x1 * 2, y1); + if((pixel & 0x0f) > 0) + drawSprPixel(pixel & 0xf, x, y, x1 * 2 + 1, y1); + } + } + } + else{ + for(byte y1 = 0; y1 < h; y1 ++) + if(y1 + y >= -h && y1 + y < 128 + h){ + for(byte x1 = 0; x1 < w; x1++) + if(x1 + x >= -w && x1 + x < 128 + w){ + pixel = readMem(adr + x1 + y1 * w); + if((pixel & 0xf0) > 0) + drawRotateSprPixel(pixel >> 4, x, y, x1 * 2, y1, w, h / 2, c, s); + if((pixel & 0x0f) > 0) + drawRotateSprPixel(pixel & 0xf, x, y, x1 * 2 + 1, y1, w, h / 2, c, s); + } + } + } +} + +void drawImg(int16_t a, uint16_t x, uint16_t y, int16_t w, int16_t h){ + if(imageSize > 1){ + drawImgS(a, x, y, w, h); + return; + } + uint8_t p, color; + for(int16_t yi = 0; yi < h; yi++) + for(int16_t xi = 0; xi < w; xi++){ + p = readMem(a); + color = (p & 0xf0) >> 4; + if(color > 0){ + setPix(xi + x, yi + y, color); + } + xi++; + color = p & 0x0f; + if(color > 0){ + setPix(xi + x, yi + y, color); + } + a++; + } +} + +void drawImgRLE(int16_t adr, uint16_t x1, uint16_t y1, int16_t w, int16_t h){ + if(imageSize > 1){ + drawImgRLES(adr, x1, y1, w, h); + return; + } + int16_t i = 0; + byte repeat = readMem(adr); + adr++; + int8_t color1 = (readMem(adr) & 0xf0) >> 4; + int8_t color2 = readMem(adr) & 0xf; + while(i < w * h){ + if(repeat > 0x81){ + if(color1 > 0){ + setPix(x1 + i % w, y1 + i / w, color1); + } + if(color2 > 0){ + setPix(x1 + i % w + 1, y1 + i / w, color2); + } + i += 2; + adr++; + repeat--; + color1 = (readMem(adr) & 0xf0) >> 4; + color2 = readMem(adr) & 0xf; + } + else if(repeat == 0x81){ + repeat = readMem(adr); + adr++; + color1 = (readMem(adr) & 0xf0) >> 4; + color2 = readMem(adr) & 0xf; + } + else if(repeat > 0){ + if(color1 > 0){ + setPix(x1 + i % w, y1 + i / w, color1); + } + if(color2 > 0){ + setPix(x1 + i % w + 1, y1 + i / w, color2); + } + i += 2; + repeat--; + } + else if(repeat == 0){ + adr++; + repeat = readMem(adr); + adr++; + color1 = (readMem(adr) & 0xf0) >> 4; + color2 = readMem(adr) & 0xf; + } + } + } + +void drawImgS(int16_t a, uint16_t x, uint16_t y, int16_t w, int16_t h){ + uint8_t p, jx, jy, color, s; + s = imageSize; + for(int16_t yi = 0; yi < h; yi++) + for(int16_t xi = 0; xi < w; xi++){ + p = readMem(a); + color = (p & 0xf0) >> 4; + if(color > 0){ + for(jx = 0; jx < s; jx++) + for(jy = 0; jy < s; jy++) + setPix(xi * s + x + jx, yi * s + y + jy, color); + } + xi++; + color = p & 0x0f; + if(color > 0){ + for(jx = 0; jx < s; jx++) + for(jy = 0; jy < s; jy++) + setPix(xi * s + x + jx, yi * s + y + jy, color); + } + a++; + } +} + +void drawImgRLES(int16_t adr, uint16_t x1, uint16_t y1, int16_t w, int16_t h){ + int16_t i = 0; + uint8_t jx, jy, s; + s = imageSize; + byte repeat = readMem(adr); + adr++; + int8_t color1 = (readMem(adr) & 0xf0) >> 4; + int8_t color2 = readMem(adr) & 0xf; + while(i < w * h){ + if(repeat > 0x81){ + if(color1 > 0){ + for(jx = 0; jx < s; jx++) + for(jy = 0; jy < s; jy++) + setPix(x1 + (i % w) * s + jx, y1 + i / w * s + jy, color1); + } + if(color2 > 0){ + for(jx = 0; jx < s; jx++) + for(jy = 0; jy < s; jy++) + setPix(x1 + (i % w) * s + s + jx, y1 + i / w * s + jy, color2); + } + i += 2; + adr++; + repeat--; + color1 = (readMem(adr) & 0xf0) >> 4; + color2 = readMem(adr) & 0xf; + } + else if(repeat == 0x81){ + repeat = readMem(adr); + adr++; + color1 = (readMem(adr) & 0xf0) >> 4; + color2 = readMem(adr) & 0xf; + } + else if(repeat > 0){ + if(color1 > 0){ + for(jx = 0; jx < s; jx++) + for(jy = 0; jy < s; jy++) + setPix(x1 + (i % w) * s + jx, y1 + i / w * s + jy, color1); + } + if(color2 > 0){ + for(jx = 0; jx < s; jx++) + for(jy = 0; jy < s; jy++) + setPix(x1 + (i % w) * s + s + jx, y1 + i / w * s + jy, color2);; + } + i += 2; + repeat--; + } + else if(repeat == 0){ + adr++; + repeat = readMem(adr); + adr++; + color1 = (readMem(adr) & 0xf0) >> 4; + color2 = readMem(adr) & 0xf; + } + } + } + +void loadTile(int16_t adr, uint8_t iwidth, uint8_t iheight, uint8_t width, uint8_t height){ + tile.adr = adr; + tile.imgwidth = iwidth; + tile.imgheight = iheight; + tile.width = width; + tile.height = height; + } + +void drawTile(int16_t x0, int16_t y0){ + int16_t x, y, nx, ny; + uint16_t imgadr; + tile.x = x0; + tile.y = y0; + for(x = 0; x < tile.width; x++){ + nx = x0 + x * tile.imgwidth; + for(y = 0; y < tile.height; y++){ + ny = y0 + y * tile.imgheight; + if(nx > 0 && nx < 128 && ny > 0 && ny < 128){ + imgadr = readInt(tile.adr + (x + y * tile.width) * 2); + if(imgadr > 0) + drawImg(imgadr, nx, ny, tile.imgwidth, tile.imgheight); + } + } + } + } + +void drwLine(int16_t x1, int16_t y1, int16_t x2, int16_t y2) { + int16_t deltaX = abs(x2 - x1); + int16_t deltaY = abs(y2 - y1); + int16_t signX = x1 < x2 ? 1 : -1; + int16_t signY = y1 < y2 ? 1 : -1; + int16_t error = deltaX - deltaY; + int16_t error2; + setPix(x2, y2, color); + while(x1 != x2 || y1 != y2){ + setPix(x1, y1, color); + error2 = error * 2; + if(error2 > -deltaY){ + error -= deltaY; + x1 += signX; + } + if(error2 < deltaX){ + error += deltaX; + y1 += signY; + } + } + } + +inline void setPix(byte x, byte y, byte c){ + byte xi = x / 2; + if(x >= 0 && x < 128 && y >= 0 && y < 128){ + if(x & 1) + screen[xi][y] = (screen[xi][y] & 0xf0) + c; + else + screen[xi][y] = (screen[xi][y] & 0x0f) + ( c << 4); + line_is_draw[y] |= 1 + x / 64; + } +} + +byte getPix(byte x, byte y){ + byte b = 0; + byte xi = x / 2; + if(x >= 0 && x < 128 && y >= 0 && y < 128){ + if(x % 2 == 0) + b = (screen[xi][y] & 0xf0) >> 4; + else + b = (screen[xi][y] & 0x0f); + } + return b; +} + +void changePalette(uint8_t n, uint16_t c){ + palette[n] = c; +} + +void scrollScreen(uint8_t step, uint8_t direction){ + uint8_t bufPixel; + if(direction == 2){ + for(uint8_t y = 0; y < 128; y++){ + bufPixel = screen[0][ y]; + for(uint8_t x = 1; x < 64; x++){ + if(screen[x - 1][y] != screen[x][y]) + line_is_draw[y] |= 1 + x / 32; + screen[x - 1][ y] = screen[x][y]; + } + if(screen[63][y] != bufPixel) + line_is_draw[y] |= 1; + screen[63][ y] = bufPixel; + } + for(uint8_t n = 0; n < 32; n++) + sprite_table[n].x--; + } + else if(direction == 1){ + for(uint8_t x = 0; x < 64; x++){ + bufPixel = screen[x][0]; + for(uint8_t y = 1; y < 128; y++){ + if(screen[x][y-1] != screen[x][y]) + line_is_draw[y] |= 1 + x / 32; + screen[x][y - 1] = screen[x][y]; + } + if(screen[x][127] != bufPixel) + line_is_draw[127] |= 2; + screen[x][127] = bufPixel; + } + for(uint8_t n = 0; n < 32; n++) + sprite_table[n].y++; + } + else if(direction == 0){ + for(uint8_t y = 0; y < 128; y++){ + bufPixel = screen[63][y]; + for(uint8_t x = 63; x > 0; x--){ + if(screen[x][y] != screen[x - 1][y]) + line_is_draw[y] |= 1 + x / 32; + screen[x][y] = screen[x - 1][y]; + } + if(screen[0][y] != bufPixel) + line_is_draw[y] |= 1; + screen[0][y] = bufPixel; + } + for(uint8_t n = 0; n < 32; n++) + sprite_table[n].x++; + } + else { + for(uint8_t x = 0; x < 64; x++){ + bufPixel = screen[x][127]; + for(uint8_t y = 127; y > 0; y--){ + if(screen[x][y] != screen[x][y - 1]) + line_is_draw[y] |= 1 + x / 32; + screen[x][y] = screen[x][y - 1]; + } + if(screen[x][0] != bufPixel) + line_is_draw[0] |= 1 + x / 32; + screen[x][0] = bufPixel; + } + for(uint8_t n = 0; n < 32; n++) + sprite_table[n].y--; + } + if(tile.adr > 0) + tileDrawLine(step, direction); +} + +void tileDrawLine(uint8_t step, uint8_t direction){ + int16_t x,y,x0,y0,y1,nx,ny; + uint16_t imgadr; + if(direction == 2){ + tile.x -= step*2; + x0 = tile.x; + y0 = tile.y; + x = (127 - x0) / tile.imgwidth; + nx = x0 + x * tile.imgwidth; + if(x < tile.width && x >= 0){ + for(y = 0; y < tile.height; y++){ + ny = y0 + y * tile.imgheight; + if(ny > 0 && ny < 128){ + imgadr = readInt(tile.adr + (x + y * tile.width) * 2); + if(imgadr > 0) + drawImg(imgadr, nx, ny, tile.imgwidth, tile.imgheight); + else + fillRect(nx, ny, tile.imgwidth, tile.imgheight, bgcolor); + } + } + } + else if(tile.width * tile.imgwidth + x0 >= 0){ + y0 = (y0 > 0) ? y0 : 0; + y1 = (tile.y + tile.height * tile.imgheight < 128) ? tile.y + tile.height * tile.imgheight - y0 : 127 - y0; + if(y0 < 127 && y1 > 0) + fillRect(127 - step * 2, y0, step * 2, y1, bgcolor); + } + } + else if(direction == 1){ + tile.y -= step; + x0 = tile.x; + y0 = tile.y; + y = (127 - y0) / tile.imgheight; + ny = y0 + y * tile.imgheight; + if(y < tile.height && y >= 0) + for(x = 0; x < tile.width; x++){ + nx = x0 + x * tile.imgwidth; + if(nx > 0 && nx < 128){ + imgadr = readInt(tile.adr + (x + y * tile.width) * 2); + if(imgadr > 0) + drawImg(imgadr, nx, ny, tile.imgwidth, tile.imgheight); + else + fillRect(nx, ny, tile.imgwidth, tile.imgheight, bgcolor); + } + } + } + else if(direction == 0){ + tile.x += step*2; + x0 = tile.x; + y0 = tile.y; + x = (0 - x0) / tile.imgwidth; + nx = x0 + x * tile.imgwidth; + if(x0 < 0 && x >= 0){ + for(y = 0; y < tile.height; y++){ + ny = y0 + y * tile.imgheight; + if(ny > 0 && ny < 128){ + imgadr = readInt(tile.adr + (x + y * tile.width) * 2); + if(imgadr > 0) + drawImg(imgadr, nx, ny, tile.imgwidth, tile.imgheight); + else + fillRect(nx, ny, tile.imgwidth, tile.imgheight, bgcolor); + } + } + } + else if(x0 < 128){ + y0 = (y0 > 0) ? y0 : 0; + y1 = (tile.y + tile.height * tile.imgheight < 128) ? tile.y + tile.height * tile.imgheight - y0 : 127 - y0; + if(y0 < 127 && y1 > 0) + fillRect(0, y0, step * 2, y1, bgcolor); + } + } + else if(direction == 3){ + tile.y += step; + x0 = tile.x; + y0 = tile.y; + y = (0 - y0) / tile.imgheight; + ny = y0 + y * tile.imgheight; + if(y < tile.height && y >= 0) + for(x = 0; x < tile.width; x++){ + if(nx > 0 && nx < 128){ + imgadr = readInt(tile.adr + (x + y * tile.width) * 2); + if(imgadr > 0) + drawImg(imgadr, nx, ny, tile.imgwidth, tile.imgheight); + else + fillRect(nx, ny, tile.imgwidth, tile.imgheight, bgcolor); + } + } + } + } + +void charLineUp(byte n){ + clearScr(); + for(uint16_t i = 0; i < 336 - n * 21; i++){ + charArray[i] = charArray[i + n * 21]; + putchar(charArray[i], (i % 21) * 6, (i / 21) * 8); + } +} + +void setCharX(int8_t x){ + regx = x; +} + +void setCharY(int8_t y){ + regy = y; +} + +void printc(char c, byte fc, byte bc){ + if(c == '\n'){ + fillRect(regx * 6, regy * 8, 127 - regx * 6, 8, 0); + for(byte i = regx; i <= 21; i++){ + charArray[regx + regy * 21] = ' '; + } + regy++; + regx = 0; + if(regy > 15){ + regy = 15; + charLineUp(1); + } + } + else if(c == '\t'){ + for(byte i = 0; i <= regx % 5; i++){ + fillRect(regx * 6, regy * 8, 6, 8, 0); + charArray[regx + regy * 21] = ' '; + regx++; + if(regx > 21){ + regy++; + regx = 0; + if(regy > 15){ + regy = 15; + charLineUp(1); + } + } + } + } + else{ + fillRect(regx * 6, regy * 8, 6, 8, 0); + putchar(c, regx * 6, regy * 8); + charArray[regx + regy * 21] = c; + regx++; + if(regx > 20){ + regy++; + regx = 0; + if(regy > 15){ + regy = 15; + charLineUp(1); + } + } + } +} + +void setColor(uint8_t c){ + color = c & 0xf; +} + +void fillRect(int8_t x, int8_t y, uint8_t w, uint8_t h, uint8_t c){ + for(int16_t jx = x; jx < x + w; jx++) + for(int16_t jy = y; jy < y + h; jy++) + setPix(jx, jy, c); +} + +void putString(char s[], int8_t y){ + int8_t i = 0; + while(s[i] != 0 && i < 21){ + putchar(s[i], i * 6, y); + i++; + } +} + +void putchar(char c, uint8_t x, uint8_t y) { + for(int8_t i=0; i<5; i++ ) { // Char bitmap = 5 columns + uint8_t line = pgm_read_byte(&font_a[c * 5 + i]); + for(int8_t j=0; j<8; j++, line >>= 1) { + if(line & 1) + setPix(x+i, y+j, color); + } + } +} + diff --git a/file_manager.ino b/file_manager.ino new file mode 100644 index 0000000..2b450c1 --- /dev/null +++ b/file_manager.ino @@ -0,0 +1,89 @@ +void fileList(String path) { + Dir dir = SPIFFS.openDir(path); + char s[32]; + char thisF[32]; + int16_t lst = 1; + int16_t pos = 0; + int16_t startpos = 0; + int16_t fileCount = 0; + int16_t skip = 0; + while (dir.next()) { + File entry = dir.openFile("r"); + strcpy(s, entry.name()); + Serial.println(s); + entry.close(); + fileCount++; + } + while(1){ + skip = startpos; + lst = 1; + dir = SPIFFS.openDir(path); + setColor(1); + while (dir.next() && lst < 14) { + File entry = dir.openFile("r"); + if(skip > 0){ + skip--; + } + else{ + strcpy(s, entry.name()); + if(lst + startpos - 1 == pos) + strcpy(thisF, entry.name()); + putString(s, lst * 8); + lst++; + } + entry.close(); + } + if(lst + startpos - 1 < pos){ + if(fileCount > pos) + startpos++; + else + pos--; + } + else if(startpos > pos){ + startpos = pos; + } + setColor(8); + drwLine(2, (pos - startpos + 1) * 8, 124, (pos - startpos + 1) * 8); + drwLine(2, (pos - startpos + 1) * 8 + 7, 124, (pos - startpos + 1) * 8 + 7); + redrawScreen(); + clearScr(); + while(thiskey != 0){ + getKey(); + delay(100); + } + while(thiskey == 0){ + getKey(); + delay(100); + } + if(thiskey & 16){//ok + loadFromSPIFS(thisF); + return; + } + else if(thiskey & 2){//down + if(pos < fileCount - 1) + pos++; + } + else if(thiskey & 1){//up + if(pos > 0) + pos--; + } + if(thiskey & 4)//left + return; + } +} + +void loadFromSPIFS(char fileName[]){ + int i; + File f = SPIFFS.open(fileName, "r"); + if(f.size() < RAM_SIZE) + for(i = 0; i < f.size(); i++){ + mem[i] = (uint8_t)f.read(); + } + Serial.print(F("loaded ")); + Serial.print(i); + Serial.println(F(" byte")); + Serial.print(F("free heap ")); + Serial.println(system_get_free_heap_size()); + f.close(); //Close file +} + diff --git a/font_a.c b/font_a.c new file mode 100644 index 0000000..c7c1d09 --- /dev/null +++ b/font_a.c @@ -0,0 +1,270 @@ +#ifdef __AVR__ + #include + #include +#elif defined(ESP8266) + #include +#else + #define PROGMEM +#endif + +// Standard ASCII 5x7 font + +static const unsigned char font_a[] PROGMEM = { +0x00,0x00,0x00,0x00,0x00, // NUL +0x3E,0x55,0x51,0x55,0x3E, // SOH +0x3E,0x6B,0x6F,0x6B,0x3E, // STX +0x0C,0x1E,0x3C,0x1E,0x0C, // ETX +0x08,0x1C,0x3E,0x1C,0x08, // EOT +0x1C,0x4A,0x7F,0x4A,0x1C, // ENQ +0x18,0x5C,0x7F,0x5C,0x18, // ACK +0x00,0x1C,0x1C,0x1C,0x00, // BEL +0x7F,0x63,0x63,0x63,0x7F, // BS +0x00,0x1C,0x14,0x1C,0x00, // TAB +0x7F,0x63,0x6B,0x63,0x7F, // LF +0x30,0x48,0x4D,0x33,0x07, // VT +0x06,0x29,0x79,0x29,0x06, // FF +0x20,0x50,0x3F,0x02,0x0C, // CR +0x60,0x7F,0x05,0x35,0x3F, // SO +0x2A,0x1C,0x77,0x1C,0x2A, // SI +0x00,0x7F,0x3E,0x1C,0x08, // DLE +0x08,0x1C,0x3E,0x7F,0x00, // DC1 +0x14,0x22,0x7F,0x22,0x14, // DC2 +0x00,0x5F,0x00,0x5F,0x00, // DC3 +0x06,0x09,0x7F,0x01,0x7F, // DC4 +0x4A,0x55,0x55,0x55,0x29, // NAK +0x60,0x60,0x60,0x60,0x60, // SYN +0x54,0x62,0x7F,0x62,0x54, // ETB +0x08,0x04,0x7E,0x04,0x08, // CAN +0x08,0x10,0x3F,0x10,0x08, // EM +0x08,0x08,0x2A,0x1C,0x08, // SUB +0x08,0x1C,0x2A,0x08,0x08, // ESC +0x1C,0x10,0x10,0x10,0x10, // FS +0x1C,0x3E,0x08,0x3E,0x1C, // GS +0x30,0x3C,0x3F,0x3C,0x30, // RS +0x06,0x1E,0x7E,0x1E,0x06, // US +0x00,0x00,0x00,0x00,0x00, // SPC +0x00,0x00,0x5F,0x00,0x00, // symbol '!' +0x00,0x07,0x00,0x07,0x00, // symbol +0x14,0x7F,0x14,0x7F,0x14, // symbol '#' +0x24,0x2A,0x7F,0x2A,0x12, // symbol '$' +0x23,0x13,0x08,0x64,0x62, // symbol '%' +0x36,0x49,0x56,0x20,0x50, // symbol '&' +0x00,0x00,0x07,0x00,0x00, // symbol ''' +0x00,0x1C,0x22,0x41,0x00, // symbol '(' +0x00,0x41,0x22,0x1C,0x00, // symbol ')' +0x14,0x08,0x3E,0x08,0x14, // symbol '*' +0x08,0x08,0x3E,0x08,0x08, // symbol '+' +0x00,0x20,0x41,0x01,0x00, // symbol ',' +0x08,0x08,0x08,0x08,0x08, // symbol '-' +0x00,0x60,0x60,0x00,0x00, // symbol '.' +0x20,0x10,0x08,0x04,0x02, // symbol '/' +0x3E,0x51,0x49,0x45,0x3E, // digit '0' +0x44,0x42,0x7F,0x40,0x40, // digit '1' +0x42,0x61,0x51,0x49,0x46, // digit '2' +0x21,0x41,0x45,0x4B,0x31, // digit '3' +0x18,0x14,0x12,0x7F,0x10, // digit '4' +0x27,0x45,0x45,0x45,0x39, // digit '5' +0x3C,0x4A,0x49,0x49,0x30, // digit '6' +0x01,0x71,0x09,0x05,0x03, // digit '7' +0x36,0x49,0x49,0x49,0x36, // digit '8' +0x06,0x49,0x49,0x29,0x1E, // digit '9' +0x00,0x6C,0x6C,0x00,0x00, // symbol ':' +0x00,0x2C,0x59,0x01,0x00, // symbol ';' +0x08,0x14,0x22,0x41,0x00, // symbol '<' +0x14,0x14,0x14,0x14,0x14, // symbol '=' +0x00,0x41,0x22,0x14,0x08, // symbol '>' +0x02,0x01,0x51,0x09,0x06, // symbol '?' +0x3E,0x41,0x5D,0x55,0x5E, // symbol '@' +0x7C,0x12,0x11,0x12,0x7C, // eng 'A' +0x7F,0x49,0x49,0x49,0x36, // eng 'B' +0x3E,0x41,0x41,0x41,0x22, // eng 'C' +0x7F,0x41,0x41,0x22,0x1C, // eng 'D' +0x7F,0x49,0x49,0x49,0x41, // eng 'E' +0x7F,0x09,0x09,0x09,0x01, // eng 'F' +0x3E,0x41,0x49,0x49,0x7A, // eng 'G' +0x7F,0x08,0x08,0x08,0x7F, // eng 'H' +0x00,0x41,0x7F,0x41,0x00, // eng 'I' +0x20,0x40,0x41,0x3F,0x01, // eng 'J' +0x7F,0x08,0x14,0x22,0x41, // eng 'K' +0x7F,0x40,0x40,0x40,0x60, // eng 'L' +0x7F,0x02,0x0C,0x02,0x7F, // eng 'M' +0x7F,0x04,0x08,0x10,0x7F, // eng 'N' +0x3E,0x41,0x41,0x41,0x3E, // eng 'O' +0x7F,0x09,0x09,0x09,0x06, // eng 'P' +0x3E,0x41,0x51,0x21,0x5E, // eng 'Q' +0x7F,0x09,0x19,0x29,0x46, // eng 'R' +0x46,0x49,0x49,0x49,0x31, // eng 'S' +0x03,0x01,0x7F,0x01,0x03, // eng 'T' +0x3F,0x40,0x40,0x40,0x3F, // eng 'U' +0x1F,0x20,0x40,0x20,0x1F, // eng 'V' +0x3F,0x40,0x3C,0x40,0x3F, // eng 'W' +0x63,0x14,0x08,0x14,0x63, // eng 'X' +0x07,0x08,0x70,0x08,0x07, // eng 'Y' +0x61,0x51,0x49,0x45,0x43, // eng 'Z' +0x00,0x7F,0x41,0x41,0x00, // symbol '[' +0x02,0x04,0x08,0x10,0x20, // symbol '\' +0x00,0x41,0x41,0x7F,0x00, // symbol ']' +0x04,0x02,0x01,0x02,0x04, // symbol '^' +0x40,0x40,0x40,0x40,0x40, // symbol '_' +0x00,0x01,0x02,0x04,0x00, // symbol '`' +0x20,0x54,0x54,0x54,0x78, // eng 'a' +0x7F,0x48,0x44,0x44,0x38, // eng 'b' +0x38,0x44,0x44,0x44,0x48, // eng 'c' +0x38,0x44,0x44,0x48,0x7F, // eng 'd' +0x38,0x54,0x54,0x54,0x18, // eng 'e' +0x08,0x7E,0x09,0x01,0x02, // eng 'f' +0x08,0x54,0x54,0x58,0x3C, // eng 'g' +0x7F,0x08,0x04,0x04,0x78, // eng 'h' +0x00,0x44,0x7D,0x40,0x00, // eng 'i' +0x20,0x40,0x44,0x3D,0x00, // eng 'j' +0x7F,0x10,0x10,0x28,0x44, // eng 'k' +0x00,0x41,0x7F,0x40,0x00, // eng 'l' +0x7C,0x04,0x78,0x04,0x78, // eng 'm' +0x7C,0x08,0x04,0x04,0x78, // eng 'n' +0x38,0x44,0x44,0x44,0x38, // eng 'o' +0x7C,0x14,0x14,0x14,0x08, // eng 'p' +0x08,0x14,0x14,0x0C,0x7C, // eng 'q' +0x7C,0x08,0x04,0x04,0x08, // eng 'r' +0x48,0x54,0x54,0x54,0x24, // eng 's' +0x04,0x3F,0x44,0x40,0x20, // eng 't' +0x3C,0x40,0x40,0x20,0x7C, // eng 'u' +0x1C,0x20,0x40,0x20,0x1C, // eng 'v' +0x3C,0x40,0x38,0x40,0x3C, // eng 'w' +0x44,0x28,0x10,0x28,0x44, // eng 'x' +0x0C,0x50,0x50,0x50,0x3C, // eng 'y' +0x44,0x64,0x54,0x4C,0x44, // eng 'z' +0x00,0x08,0x36,0x41,0x00, // symbol '{' +0x00,0x00,0x7F,0x00,0x00, // symbol '|' +0x00,0x41,0x36,0x08,0x00, // symbol '}' +0x02,0x01,0x02,0x04,0x02, // symbol '~' +0x70,0x48,0x44,0x48,0x70, // DEL +0x00,0x0E,0x11,0x0E,0x00, // symbol '-' +0x00,0x12,0x1F,0x10,0x00, // symbol '¦' +0x00,0x12,0x19,0x16,0x00, // symbol '-' +0x00,0x11,0x15,0x0B,0x00, // symbol '¬' +0x00,0x07,0x04,0x1F,0x00, // symbol 'L' +0x00,0x17,0x15,0x09,0x00, // symbol '-' +0x00,0x0E,0x15,0x09,0x00, // symbol '+' +0x00,0x01,0x1D,0x03,0x00, // symbol '+' +0x00,0x0A,0x15,0x0A,0x00, // symbol 'T' +0x00,0x12,0x15,0x0E,0x00, // symbol '+' +0x00,0x04,0x04,0x04,0x00, // symbol '+' +0x7F,0x7F,0x7F,0x7F,0x7F, // symbol '-' +0x3E,0x00,0x00,0x00,0x00, // symbol '-' +0x3E,0x3E,0x00,0x00,0x00, // symbol '-' +0x3E,0x3E,0x00,0x3E,0x00, // symbol '¦' +0x3E,0x3E,0x00,0x3E,0x3E, // symbol '¦' +0x00,0x01,0x02,0x04,0x08, // symbol '-' +0x40,0x01,0x03,0x06,0x0C, // symbol '-' +0x50,0x21,0x43,0x06,0x0D, // symbol '-' +0x58,0x31,0x63,0x46,0x0D, // symbol '¦' +0x5A,0x35,0x6B,0x56,0x2D, // symbol +0x5B,0x37,0x6F,0x5E,0x3D, // symbol '•' +0x40,0x00,0x40,0x00,0x40, // symbol 'v' +0x60,0x00,0x40,0x00,0x40, // symbol '¦' +0x60,0x00,0x70,0x00,0x40, // symbol '-' +0x60,0x00,0x70,0x00,0x78, // symbol 'г' +0x7C,0x00,0x40,0x00,0x40, // symbol 'L' +0x7C,0x00,0x7E,0x00,0x40, // symbol '¦' +0x7C,0x00,0x7E,0x00,0x7F, // symbol 'T' +0x1C,0x77,0x41,0x41,0x41, // symbol 'T' +0x41,0x41,0x41,0x41,0x41, // symbol '¦' +0x41,0x41,0x41,0x7F,0x00, // symbol '¦' +0x1C,0x77,0x41,0x5D,0x5D, // symbol '=' +0x41,0x41,0x41,0x5D,0x5D, // symbol 'Ў' +0x5D,0x5D,0x41,0x5D,0x5D, // symbol 'ў' +0x5D,0x5D,0x41,0x7F,0x00, // symbol '¬' +0x22,0x1C,0x14,0x1C,0x22, // symbol '¤' +0x00,0x08,0x1C,0x08,0x00, // symbol 'г' +0x00,0x00,0x77,0x00,0x00, // symbol '¬' +0x46,0x5D,0x55,0x5D,0x31, // symbol '¬' +0x7C,0x55,0x54,0x55,0x44, // rus 'Ё' +0x08,0x08,0x2A,0x08,0x08, // symbol 'L' +0x00,0x14,0x08,0x14,0x00, // symbol 'Є' +0x08,0x14,0x22,0x08,0x14, // symbol 'L' +0x7F,0x41,0x71,0x31,0x1F, // symbol '-' +0x03,0x05,0x7F,0x05,0x03, // symbol '-' +0x22,0x14,0x7F,0x55,0x22, // symbol '-' +0x02,0x55,0x7D,0x05,0x02, // symbol 'Ї' +0x06,0x09,0x09,0x06,0x00, // symbol '°' +0x44,0x44,0x5F,0x44,0x44, // symbol '¦' +0x1C,0x14,0x1C,0x22,0x7F, // symbol '¦' +0x20,0x3E,0x61,0x3E,0x20, // symbol '¦' +0x20,0x50,0x3F,0x02,0x0C, // symbol '¦' +0x00,0x79,0x41,0x78,0x00, // symbol '¦' +0x44,0x3C,0x04,0x7C,0x44, // symbol 'T' +0x00,0x00,0x08,0x00,0x00, // symbol '·' +0x38,0x55,0x54,0x55,0x18, // rus 'ё' +0x7E,0x08,0x10,0x7F,0x01, // symbol '№' +0x08,0x10,0x08,0x04,0x02, // symbol 'є' +0x14,0x08,0x22,0x14,0x08, // symbol '¦' +0x0E,0x06,0x0A,0x10,0x20, // symbol '+' +0x20,0x10,0x0A,0x06,0x0E, // symbol '+' +0x38,0x30,0x28,0x04,0x02, // symbol '+' +0x02,0x04,0x28,0x30,0x38, // symbol 'ї' +0x7E,0x11,0x11,0x11,0x7E, // rus 'А' +0x7F,0x49,0x49,0x49,0x31, // rus 'Б' +0x7F,0x49,0x49,0x49,0x36, // rus 'В' +0x7F,0x01,0x01,0x01,0x03, // rus 'Г' +0x40,0x7F,0x03,0x7F,0x01, // rus 'Д' +0x7F,0x49,0x49,0x49,0x41, // rus 'Е' +0x77,0x08,0x7F,0x08,0x77, // rus 'Ж' +0x41,0x49,0x49,0x49,0x36, // rus 'З' +0x7F,0x10,0x08,0x04,0x7F, // rus 'И' +0x7C,0x21,0x12,0x09,0x7C, // rus 'Й' +0x7F,0x08,0x14,0x22,0x41, // rus 'К' +0x40,0x3E,0x01,0x01,0x7F, // rus 'Л' +0x7F,0x02,0x0C,0x02,0x7F, // rus 'М' +0x7F,0x08,0x08,0x08,0x7F, // rus 'Н' +0x3E,0x41,0x41,0x41,0x3E, // rus 'О' +0x7F,0x01,0x01,0x01,0x7F, // rus 'П' +0x7F,0x09,0x09,0x09,0x06, // rus 'Р' +0x3E,0x41,0x41,0x41,0x22, // rus 'С' +0x01,0x01,0x7F,0x01,0x01, // rus 'Т' +0x07,0x48,0x48,0x48,0x3F, // rus 'У' +0x0E,0x11,0x7F,0x11,0x0E, // rus 'Ф' +0x63,0x14,0x08,0x14,0x63, // rus 'Х' +0x7F,0x40,0x40,0x7F,0x40, // rus 'Ц' +0x07,0x08,0x08,0x08,0x7F, // rus 'Ч' +0x7F,0x40,0x7F,0x40,0x7F, // rus 'Ш' +0x7F,0x40,0x7F,0x40,0x7F, // rus 'Щ' +0x01,0x7F,0x48,0x48,0x30, // rus 'Ъ' +0x7F,0x48,0x48,0x30,0x7F, // rus 'Ы' +0x7F,0x48,0x48,0x48,0x30, // rus 'Ь' +0x22,0x41,0x49,0x49,0x3E, // rus 'Э' +0x7F,0x08,0x3E,0x41,0x3E, // rus 'Ю' +0x46,0x29,0x19,0x09,0x7F, // rus 'Я' +0x20,0x54,0x54,0x54,0x78, // rus 'а' +0x3C,0x4A,0x4A,0x49,0x31, // rus 'б' +0x7C,0x54,0x54,0x54,0x28, // rus 'в' +0x7C,0x04,0x04,0x04,0x0C, // rus 'г' +0x40,0x71,0x09,0x79,0x01, // rus 'д' +0x38,0x54,0x54,0x54,0x18, // rus 'е' +0x6C,0x10,0x7C,0x10,0x6C, // rus 'ж' +0x44,0x54,0x54,0x54,0x28, // rus 'з' +0x7C,0x20,0x10,0x08,0x7C, // rus 'и' +0x7C,0x40,0x26,0x10,0x7C, // rus 'й' +0x7C,0x10,0x10,0x28,0x44, // rus 'к' +0x40,0x38,0x04,0x04,0x7C, // rus 'л' +0x7C,0x08,0x10,0x08,0x7C, // rus 'м' +0x7C,0x10,0x10,0x10,0x7C, // rus 'н' +0x38,0x44,0x44,0x44,0x38, // rus 'о' +0x7C,0x04,0x04,0x04,0x7C, // rus 'п' +0x7C,0x14,0x14,0x14,0x08, // rus 'р' +0x38,0x44,0x44,0x44,0x48, // rus 'с' +0x04,0x04,0x7C,0x04,0x04, // rus 'т' +0x0C,0x50,0x50,0x50,0x3C, // rus 'у' +0x18,0x24,0x7C,0x49,0x30, // rus 'ф' +0x44,0x28,0x10,0x28,0x44, // rus 'х' +0x7C,0x40,0x40,0x7C,0x40, // rus 'ц' +0x0C,0x10,0x10,0x10,0x7C, // rus 'ч' +0x7C,0x40,0x7C,0x40,0x7C, // rus 'ш' +0x7C,0x40,0x7C,0x40,0x7C, // rus 'щ' +0x04,0x7C,0x50,0x50,0x20, // rus 'ъ' +0x7C,0x50,0x50,0x20,0x7C, // rus 'ы' +0x7C,0x50,0x50,0x50,0x20, // rus 'ь' +0x28,0x44,0x54,0x54,0x38, // rus 'э' +0x7C,0x10,0x38,0x44,0x38, // rus 'ю' +0x48,0x34,0x14,0x14,0x7C // rus 'я' +}; + diff --git a/keyboard.ino b/keyboard.ino new file mode 100644 index 0000000..3b6afe1 --- /dev/null +++ b/keyboard.ino @@ -0,0 +1,42 @@ +#include + +void geti2cAdress(){ + byte error,address; + i2c_adress=0; + for(address = 1; address < 127; address++ ) + { + Wire.beginTransmission(address); + error = Wire.endTransmission(); + if (error == 0){ + i2c_adress=address; + return; + } + yield(); + } +} + +void getKey(){ + byte dio_in; + Wire.beginTransmission(i2c_adress); + Wire.write(B11111111); //Конфигурация всех портов PCF8574P на клавиатуре как входа + Wire.endTransmission(); + Wire.requestFrom(i2c_adress,1); + dio_in = Wire.read(); //читаем состояние портов PCF8574P(кнопок) + thiskey = 0; + if((dio_in & 128) == 0) + thiskey |= 4; + if((dio_in & 64) == 0) + thiskey |= 8; + if((dio_in & 32) == 0) + thiskey |= 2; + if((dio_in & 16) == 0) + thiskey |= 1; //up + if((dio_in & 8) == 0) + thiskey |= 64; + if((dio_in & 4) == 0) + thiskey |= 32; + if((dio_in & 2) == 0) + thiskey |= 16; + if((dio_in & 1) == 0) + thiskey |= 128; +} diff --git a/libraries.7z b/libraries.7z new file mode 100644 index 0000000..107962f Binary files /dev/null and b/libraries.7z differ