Introduction - Overview - Commands - Sample app - Instructions - Source code
This project should make it possible to execute and edit little apps on the arduino. The real bottleneck of such a project is the limited RAM of 2 kB, so everything has to be quite squeezed (i.e. each app instruction is saved in a separate little file).
If you want to read them directly on the arduino, type:
Please contact mknot9@gmail.com for remarks or ideas.
This is a quite squeezed version of a very basic 'operating system' since it has to fit within 32k and only 2k of RAM are available.
Therefore it can (in the moment;-) only be programmed in SOBAD (a Simple Open Basic Assembler Dialect;-) which is line-based with 3-byte instructions and one optional argument. See manuals for futher details.
4AOS provides a basic GUI 'around' the command line:
_______ I_______I 1. I I I I 2. I_______I I I I 3. I____I__I
Maybe this project helps some people who want to solve little programmable tasks 'on the go' without access to a PC. The usual way to work with 4AOS is:
Since the arduino provides only 2k RAM each SOBAD instruction is stored in its own file to prevent buffering issues. For export/import of apps the XP/IP-command is provided.
All commands have to be typed directly after the '>'-prompt, exactly one space is needed before you enter an argument - no trailing spaces! Comments to the following examples start with a ':'
LS=List Directory Items
CD=Change Directory, only absolute paths (!), no leading & trailing slashes (!)
MD=Make Directory
OP='Open' File
RM=Remove File (or Directory)
FI=File Information
HD=Head of file
HA=Head all bytes
IT=Interpret as text file
IP=ImPort Program
XP=ExPort Program
GO=start program
LP=List program
SB=Switch activity Bar
XXX=Define program line=3 digits except leading '0', exactly one space is needed before the instruction
CODE: 100 DSC Create color picker: 102 V5= 111 104 V1= -32560 106 CR= 113 108 V6= 1 110 V3= 3256 112 CT= CR 114 CT+ 4 116 CC= 6 118 V2= V3 120 V2* CA 122 V2+ V1 124 CS= CQ 126 CS+ 5 128 DPX V2 130 CQ+ CC 132 CA+ 1 134 V0= 20 136 I0> CA 138 GTO 112 Main loop: 140 CA= 8 142 V8= -1 144 GSB 200 146 CC= 4 148 DQG 150 I5> CR 152 GTO 302 154 NOP Calculate new color and manage screen: 156 CB= CQ 158 V8= 0 160 GSB 200 162 V8= -1 164 CA= CB 166 CA/ 6 168 GSB 200 170 CR= 0 172 V2= CA 174 V2* V3 176 V2+ V1 178 GTO 148 Subroutine display color change: 200 CR= 118 202 CT= 119 204 CQ= CA 206 CQ* 6 208 CS= CQ 210 CS+ 5 212 DPX V8 214 RTN 302 I6> CR 304 GTO 148 Paint pixel: 306 CS= CQ 308 CS+ CC 310 CT= CR 312 CT+ CC 314 DPX V2 316 GTO 148
This Simple Open Basic Assembler Dialect is based on even (!) 3 digit-line numbers (from 100, 102 to 998 - odd numbers are used in order to implement an 'insert' function for new lines), which is an easy way to save time and space ressources on arduino. Each program starts in line 100 and after each line 2 are added - except a GTO, GSB, RTN, Ifx, JMP or JMB (Goto, Gosub, Return, If, Jump or JumpBack) instruction is used.
Each instruction is exactly 3 bytes long, followed by an optional argument that is separated by one space. All arguments are interpreted as numbers or numeric variables except after the string instruction 'SWT'. In case of endless loops tapping 'F2' brings you back to the command line.
Access to numeric variables is defined by a 3-byte code: 'TIO arg' = Type, Identifier, Operation followed by an argument. Possible types are:
Possible operations on the defined registers are:
Examples:
Further steps:
For all those who just want to try the code, not the examples, here it is (compiling results in 31960 bytes, so there's still some place for new ideas ;-)
#include <SD.h> #include <avr/pgmspace.h> // Thanks to the authors of the libs 'avr/pgmspace.h' and 'SD.h' as well as those of the code that enables touch-TFT access and FreeR1. // This project is published under the GNUv3-License. Please contact mknot9@gmail.com for remarks or ideas. #define SDIN 11 #define LCD_RS 19 #define LCD_WR 18 #define LCD_CS 17 #define LCD_REST 16 #define DCLK 15 #define DIN 14 #define CS 10 #define DOUT 8 //#define IRQ 7, #7 is depreceated on some shields, here DOUT is used as #8 (PIN 12 & 13 -> SD-SPI!) File root; unsigned int TP_X,TP_Y;//touch feedback from driver unsigned char staOcu=1,errOcu=0,couOcI=0; // cursor handling: staTEoFcuRSOR (0,1), errORoFcuRSOR (0,1), couNToFcURSORiNTERVAL (0-9), s.a. ConCur() char actBar=0, lineFeedFlag, shiftFlag=0; // action bar (in)-active while app execution (0,1), indicates that command line has 2 lines (0,1), indicates if shift was tapped (0,33) char nm[12],em[5]={"ERR "}, dt[12]={""}, h5[31], pat[20]; // Arrays for line numbers/file name on JMP, error message, present file name, command line, path char z3, z5, h3[22]; // start and end of text to be written, multi-used caching string char hf4=0,ei,e2,e3,e4; // dual used global: indicates 28 chars in DirRead or 8 byte representation of app argument, multi-used chars for input interpretation char yc=0,sk=2,tc=5,hc=0,gc,l9=0,l8=0; // Count screen lines, scaling factor of text, counter of buffer line, counter for input length, counter for gosub level, position of activity bar, shortcut support for IT-command char ts[90]={""}, c3[20],h6[31]={""},h8[31]={""},h4[31]={""}; //buffer for screen, array for app integer (-128 to 127), 3 multi used caching strings int x2, y2, f1, f2, fc=0,y4=11, vh2=0x01,vl2=0x08; //position of cursor, multi used vars int lx,ly, a3[20], v3[10], g3[10], l2, l3,l4,l6,l5=0, ry,rx,x3=0,y3; //position of touch tap, arrays for app variables and multi used integers PROGMEM prog_char tp[]={">SHIFT>ENTER>_DEL_F1 F2"}; // just a basic GUI PROGMEM prog_char ko[]={0,0,1,5, 0,5,1,9, 1,0,6,1, 1,4,6,5, 1,8,6,9, 6,0,7,5,6,5,7,9}; //lots of vectors in order to display ASCII characters PROGMEM prog_char mo[]={13,1,3,5, 13,-1,6,0, 6,0,7,9, 13,1,0,0, 0,0,1,9, 13,-1,3,5, 3,8,4,9, 3,0,7,1, 9,9,9,9, 2,5,7,6, 6,1,7,2, 2,3,7,4, 3,3,4,4, 0,0,7,1, 16,-1,6,1, 3,0,4,9, 0,8,7,9, 4,3,5,8, 12,-1,5,6, 13,-1,6,3, 12,1,3,0, 12,-1,3,0, 11,-1,3,6, 15,1,1,2, 13,-1,4,3, 5,2,6,7, 13,1,0,3, 2,0,3,3, 4,0,5,3, 3,2,4,7, 1,2,2,7, 11,1,2,7, 5,7,6,8, 14,-1,6,3, 3,8,7,9, 9999}; //x98=lots of vectors 8=<space> ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` ~ PROGMEM prog_int16_t zo[]={8,30078,12009,198,298,398,498,2009,598,13809,698,919,109,19,6008,69,694,4079,17,12,235,26,6,1245,0,2,4978,5049,4909,139,3209,798,19470,5,286,4670,5468,670,567,19460,35,8579,134,28356,3467,24358,14358,40,57,1840,1857,29260,579,34,2658,15368,16248,2648,8659,898,609,998,3409,89,309,9019}; PROGMEM float uo[]={98,3080139,79260,670049,7563409,540409,700919,407828,8007988,800838}; // vectors for characters that aren't easy to display void spistar() //usual TFT-touch driver... SPI Start { digitalWrite(CS,LOW); digitalWrite(DCLK,HIGH); digitalWrite(DIN,HIGH); digitalWrite(DCLK,HIGH); } //********************************************************** void WriteCharTo7843(unsigned char num) //SPI Write Data to Touch { unsigned char count=0; unsigned char temp; unsigned nop; temp=num; digitalWrite(DCLK,LOW); for(count=0;count<8;count++) { if(temp&0x80) digitalWrite(DIN,HIGH); else digitalWrite(DIN,LOW); temp=temp<<1; digitalWrite(DCLK,LOW); nop++; nop++; digitalWrite(DCLK,HIGH); nop++; nop++; } } //********************************************************** unsigned int ReadFromCharFrom7843() //SPI Read Data from Touch { unsigned nop; unsigned char count=0; unsigned int Num=0; for(count=0;count<12;count++) { Num<<=1; digitalWrite(DCLK,HIGH);//DCLK=1; _nop_();_nop_();_nop_(); nop++; digitalWrite(DCLK,LOW);//DCLK=0; _nop_();_nop_();_nop_(); nop++; if(digitalRead(DOUT)) Num++; } return(Num); } void LCD_Writ_Bus(char VH,char VL) { PORTD = VH; digitalWrite(LCD_WR,LOW); digitalWrite(LCD_WR,HIGH); PORTD = VL; digitalWrite(LCD_WR,LOW); digitalWrite(LCD_WR,HIGH); } void LCD_Write_COM(char VH,char VL) { digitalWrite(LCD_RS,LOW); LCD_Writ_Bus(VH,VL); } void LCD_Write_DATA(char VH,char VL) { digitalWrite(LCD_RS,HIGH); LCD_Writ_Bus(VH,VL); } void Lcd_Write_Com_Data(int com,int val) { LCD_Write_COM(com>>8,com); LCD_Write_DATA(val>>8,val); } void Address_set(unsigned int x1,unsigned int y1,unsigned int x2,unsigned int y9) { LCD_Write_COM(0x00,0x46);LCD_Write_DATA(x2,x1); LCD_Write_COM(0x00,0x47);LCD_Write_DATA(y9>>8,y9); LCD_Write_COM(0x00,0x48);LCD_Write_DATA(y1>>8,y1); LCD_Write_COM(0x00,0x20);LCD_Write_DATA(x1>>8,x1); LCD_Write_COM(0x00,0x21);LCD_Write_DATA(y1>>8,y1); LCD_Write_COM(0x00,0x22); } void LCD_Init(void) { digitalWrite(LCD_REST,HIGH); delay(5); digitalWrite(LCD_REST,LOW); delay(5); digitalWrite(LCD_REST,HIGH); delay(5); digitalWrite(LCD_CS,LOW); Lcd_Write_Com_Data(0x11,0x2004);Lcd_Write_Com_Data(0x13,0xCC00);Lcd_Write_Com_Data(0x15,0x2600); Lcd_Write_Com_Data(0x14,0x252A);Lcd_Write_Com_Data(0x12,0x0033);Lcd_Write_Com_Data(0x13,0xCC04); delay(1);Lcd_Write_Com_Data(0x13,0xCC06); delay(1);Lcd_Write_Com_Data(0x13,0xCC4F); delay(1);Lcd_Write_Com_Data(0x13,0x674F); Lcd_Write_Com_Data(0x11,0x2003);delay(1); Lcd_Write_Com_Data(0x30,0x2609);Lcd_Write_Com_Data(0x31,0x242C);Lcd_Write_Com_Data(0x32,0x1F23); Lcd_Write_Com_Data(0x33,0x2425);Lcd_Write_Com_Data(0x34,0x2226);Lcd_Write_Com_Data(0x35,0x2523); Lcd_Write_Com_Data(0x36,0x1C1A);Lcd_Write_Com_Data(0x37,0x131D);Lcd_Write_Com_Data(0x38,0x0B11); Lcd_Write_Com_Data(0x39,0x1210);Lcd_Write_Com_Data(0x3A,0x1315);Lcd_Write_Com_Data(0x3B,0x3619); Lcd_Write_Com_Data(0x3C,0x0D00);Lcd_Write_Com_Data(0x3D,0x000D);Lcd_Write_Com_Data(0x16,0x0007); Lcd_Write_Com_Data(0x02,0x0013);Lcd_Write_Com_Data(0x03,0x0003);Lcd_Write_Com_Data(0x01,0x0127); delay(1); Lcd_Write_Com_Data(0x08,0x0303);Lcd_Write_Com_Data(0x0A,0x000B);Lcd_Write_Com_Data(0x0B,0x0003); Lcd_Write_Com_Data(0x0C,0x0000);Lcd_Write_Com_Data(0x41,0x0000);Lcd_Write_Com_Data(0x50,0x0000); Lcd_Write_Com_Data(0x60,0x0005);Lcd_Write_Com_Data(0x70,0x000B);Lcd_Write_Com_Data(0x71,0x0000); Lcd_Write_Com_Data(0x78,0x0000);Lcd_Write_Com_Data(0x7A,0x0000);Lcd_Write_Com_Data(0x79,0x0007); Lcd_Write_Com_Data(0x07,0x0051);delay(1); Lcd_Write_Com_Data(0x07,0x0053);Lcd_Write_Com_Data(0x79,0x0000);LCD_Write_COM(0x00,0x22); digitalWrite(LCD_CS,HIGH); } void AD7843(void) { digitalWrite(CS,LOW); WriteCharTo7843(0x90); digitalWrite(DCLK,HIGH); digitalWrite(DCLK,LOW); TP_Y=ReadFromCharFrom7843(); WriteCharTo7843(0xD0); digitalWrite(DCLK,HIGH); digitalWrite(DCLK,LOW); TP_X=ReadFromCharFrom7843(); digitalWrite(CS,HIGH); // end of usual 8-bit TFT & Touch Driver } int freeR1() // thanks to arduino.cc! { extern int __heap_start, *__brkval; int v; return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); } void PaiRec(int a1, int b1, int a2, int b2) // paints rectangle relative to globals x2,y2 with scaling factor sk and color f1,f2; 240*273 shouldn't be exceeded { unsigned int p3; Address_set(x2+a1*sk,y2+b1*sk,x2+a2*sk-1,y2+b2*sk-1); for(p3=0; p3<=((a2-a1)*sk*(b2-b1)*sk); p3++) LCD_Write_DATA(f1,f2); } void ConCur() // controls cursor and error feedback for first or last character exceeding the supported input of 29 chars { char i3=0; f1=staOcu*16; if (errOcu > 0) { errOcu--; f1=staOcu*224; i3=9; } f2=f1; digitalWrite(LCD_CS,LOW); if (staOcu > 0) PaiRec(0,9-i3,8,10); else PaiRec(0,0,8,10); digitalWrite(LCD_CS,HIGH); staOcu=1-staOcu; f1=255; f2=255; } void OneColor(int w1,int v1, int w2, int v2, char c1, char c2) // Colors a bigger area in One color depending on the paramater c1 & c2 { int i3,j3; digitalWrite(LCD_CS,LOW); Address_set(w1,v1,w2,v2); for(i3=v1;i3<=v2;i3++) for (j3=w1;j3<=w2;j3++) LCD_Write_DATA(c1,c2); digitalWrite(LCD_CS,HIGH); } void ActivityBar(char c) // indicates Activity in the status Bar that takes some time { OneColor(220+l9,8,224+l9,8,0xFF,0xE0); l9=l9+4; if (l9>15) l9=0; OneColor(220+l9,8,224+l9,8,c*0xFF,c*0xE0); } void ResetInputControl() // Resets Input Control strings h5 and h8 { strcpy (h5, ">"); if (e2==124) {strcat(h5,nm); nm[0]='\0';} strcpy (h8, h5); z5=strlen(h5); hc=z5; x3=0; z3=0; lineFeedFlag=0; } void ShowStatus() // Shows the present Status of working directory, no. of items, 'open' file and free RAM { int xh,yh,zh,zg; int i,j,h; char h0[16]; strcpy(h0,h5); OneColor(0,0,239,9,0x00,0x00); f2=0xE0; h4[0]='\0'; OpenPathAndReadItems(); zg=z5; yh=y3; xh=x3; zh=z3; h=x2; strcpy(h5, pat); strcat(h5," "); itoa(fc,h3,10); strcat(h5,h3); strcat(h5," "); if (dt[0]=='\0') strcat(h5,"-"); else { j=strlen(h5); if (j+strlen(dt)>24) { for(i=0;i<6;i++) h5[j+i]=dt[i]; h5[j+i]='.'; h5[j+i+1]='.'; h5[j+i+2]='\0'; } else strcat(h5,dt); } strcat(h5," "); itoa(freeR1(),h3,10); strcat(h5,h3); j=strlen(h5); x3=0; z3=0; z5=j; sk=1; PrintAsciis(0); sk=2; OneColor(8*j+8,8,239,8,f1,f2); f2=0xFF; strcpy(h5,h0); z5=zg; y3=yh; x3=xh; z3=zh; x2=h; } void PrintAsciis(int z4) // Prints the content of h5 from z3 to the end at y-value z4 { long int p, h1, h2; int i, j, n, k9,t1,t2; char m0,m1,m2,m3; digitalWrite(LCD_CS,LOW); x2=x3; y2=z4; t1=f1; t2=f2; for(i=z3;i<z5;i++) { if ((h5[i]!='\0') && (h5[i]!='}')) { j=h5[i]-32; if ((j>94) || (j<0)) j=64; if ((j>64) && (j<94)) j=j-32; if (j==94) j=65; p=pgm_read_word_near(zo + j); h1=p/100; h2=p-h1*100; if (h2==98) p=pgm_read_float(uo + h1); h1=p/10; h1=p-h1*10; if ((h1==8)||(h1==9)) { if (h1==8) p=p/10; } else { for(j=0;j<28;j=j+4) { m0=pgm_read_byte_near(ko + j); m1=pgm_read_byte_near(ko + j +1); m2=pgm_read_byte_near(ko + j +2); m3=pgm_read_byte_near(ko + j +3); PaiRec(m0,m1,m2,m3); } f1=0x00; f2=0x00; if ((h1==0) && (p!=0)) { PaiRec(0,0,1,1); PaiRec(6,0,7,1); PaiRec(0,8,1,9); PaiRec(6,8,7,9); p=p/10; } for(k9=0;k9<6;k9++) { h1=p/10; h1=p-h1*10; if ((h1==0)||(h1==8)||(h1==9)) { if ((h1==8)) p=p/10; k9=6; } else { p=p/10; h1=(h1-1)*4; m0=pgm_read_byte_near(ko + h1); m1=pgm_read_byte_near(ko + h1 +1); m2=pgm_read_byte_near(ko + h1 +2); m3=pgm_read_byte_near(ko + h1 +3); PaiRec(m0,m1,m2,m3); } } } f1=t1; f2=t2; n=0; for(k9=0;k9<9;k9++) { h1=p/10; h1=p-h1*10; p=p/10; if ((h1==0) && (p==0)) k9=9; else { if ((h1==0) ||((h1==9)&&(n==0))) { if ((h1==0)&&(n==0)) n++; n++; } else { h1=(h1-1)*4+36*n; m0=pgm_read_byte_near(mo + h1); m1=pgm_read_byte_near(mo + h1 +1); m2=pgm_read_byte_near(mo + h1 +2); m3=pgm_read_byte_near(mo + h1 +3); if (m0>8) { for(j=0;j<m0-9;j++) PaiRec(m2+j*m1,m3+j,m2+j*m1+1,m3+j+1); if ((m3==0) && (n==0)) PaiRec(3,4,4,5); } else PaiRec(m0,m1,m2,m3); } } } x2=x2+8*sk; if (x2+8*sk>240) { x2=0; y2=y2+10*sk; } } else i=99; } digitalWrite(LCD_CS,HIGH); f1=t1; f2=t2; y3=y2; x3=x2; z3=i; } void ResetCommandLine() // Resets Command Line on start or tap in status bar { unsigned char i,j; OneColor(0,0,239,319,0x00,0x00); OneColor(0,251,239,251,0xE0,0xE0); OneColor(0,319,239,319,0xE0,0xE0); f1=16; f2=f1; z5=6; sk=1; for (i=0;i<4;i++) { for (j=0;j<6;j++) { h5[j]=pgm_read_byte_near(tp+i*6+j); } h5[6]='\0'; x3=190; z3=0; PrintAsciis(254+i*18); } sk=2; ShiftKeys(); if (strlen(pat)<2) strcpy(h5,"4AOS:SD OK!"); else strcpy(h5,pat); x3=0; z3=0; z5=strlen(h5); PrintAsciis(11); ShowStatus(); hc=1; x3=0; z3=0; z5=1; yc=1; strcpy(h5,">"); strcpy(h8,h5); PrintAsciis(31); lineFeedFlag=0; } void ShiftKeys() // displays the 'other' ascii characters (simulates the 'shift'-key on ordinary keyboards) { int xh,yh; unsigned char p,i,j,h,zg,zh; OneColor(0,252,180,318,0x00,0x00); strcpy(h4,h5); shiftFlag=33-shiftFlag; f1=6; f2=224; zg=z5; yh=y3; xh=x3; zh=z3; h=x2; z5=11; for (i=0;i<3;i++) { for (j=0;j<11;j++) { p=32+shiftFlag+i*11+j; if (p==32) p=126; if (p==96) p=32; if (p==47) p=96; if (p==97) p=47; h5[j]=p; } h5[11]='\0'; x3=0; z3=0; PrintAsciis(254+i*22); } f1=255; f2=f1; y3=yh; y2=yh; x3=xh; z3=zh; x2=h; z5=zg; strcpy(h5,h4); } void ReadAndCountDirItems(File dir) // Reads And Counts the Items of Dir, starting to read at the l5.th, up to 26 chars { char h9[31]={""}; char h10[12]; fc=0; hf4=0; // if (strlen(pat)<2) dir.rewindDirectory(); dir.rewindDirectory(); while(true) { File entry = dir.openNextFile(); if (! entry) break; // no more files if (l5<=fc) { if (hf4 < 1) { h10[0]='\0'; strcat (h10, entry.name()); if ( strlen(h10)+strlen(h9) > 26) hf4=1; else { strcat (h9, entry.name()); if (entry.isDirectory()) { strcat (h9, "/"); } strcat (h9, " "); } } } entry.close(); fc++; } strcpy (h4, h9); l5=0; } void PrintLineToDisplayAndBuffer() // displays present Command Line and saves it in Buffer, also checks if new page is needed { SaveCommandLineInBuffer(); hc=strlen(h5); if (h5[hc]==125) hc--; z5=hc; PrintAsciis(y4+yc*10*sk); yc++; if (yc>11) ClearDisplayAndPrintBuffer(); } void SaveCommandLineInBuffer() // Saves present Command Line In Buffer { unsigned char p=0; tc++; if (tc>5) tc=0; for (p=0;p<strlen(h5);p++) ts[p+15*tc]=h5[p]; } void SendCommandLineToScreen() // Prepares the Command Line to be Written { z5=strlen(h5); PrintAsciis(y4+yc*10*sk); yc=yc+(sk+1)/2; z3=0; x3=0; } void ClearDisplayAndResetControlVariables() // Clears the Screen and resets the Controls { OneColor(0,9,239,250,0x00,0x00); hc=0; yc=0; z3=0; x3=0; } void ClearDisplayAndPrintBuffer() // called when Display is full { unsigned char p; OneColor(0,9,239,250,0x00,0x00); ShowStatus(); l3=tc; hc=0; yc=0; for(p=0;p<6;p++) { l3++; if (l3>5) l3=0; for(hc=0;hc<16;hc++) { if ((ts[l3*15+hc] != '}')&&(hc<15)) { h5[hc]=ts[l3*15+hc]; } else { h5[hc]='\0'; z5=hc; z3=0; x3=0; y3=y4+10*sk*yc; PrintAsciis(y3); hc=16; } } yc++; } } void OpenPathAndReadItems() // Opens Path 'pat' and reads the dir items { pinMode(DOUT,OUTPUT); root = SD.open(pat); ReadAndCountDirItems(root); root.close(); pinMode(DOUT,INPUT); } void WriteToFile(char d8) // Writes Content of h4 in path&file h6, overriding on parameter 0, success sets e4=1 { if ((SD.exists(h6)) && (d8==0)) SD.remove(h6); e4=0; root = SD.open(h6, FILE_WRITE); if (root) { root.println(h4); root.close(); e4=1; } } void ConcatPathWithFileAndNumber(int l1) // Prepare Path for File Access with Line Number { itoa(l1,h3,10); strcpy(h6,pat); strcat(h6,dt); strcat(h6,h3); } void ReadFromFile() // Reads the next 29 (displayable) bytes from file specified in h6, from position l5, new position is saved in l6 { unsigned char p=0; l6=l5; root = SD.open(h6); root.seek(l5); while ((root.available()) && (p<29)&& (l6<32766)&& (l5<32766)) { l6++; h4[p]=root.read(); if ( ((h4[p]==10)||(h4[p]==13)) && (ei=='I') ) {l5=32766;p--;} if ( ( (h4[p]<127) && (h4[p]>31) ) || (e2=='A') ) p++; } root.close(); h4[p]='\0'; l5=0; } void GetXYfromTouchcreen() // Reads the present values from Touchscreen { unsigned char p; rx=0; ry=0; for(p=0;p<8;p++) // check 8 times to reduce noise { AD7843(); lx=0; ly=-1*TP_Y; ly=4095+ly; //4095=base for y-value, check for differences with your individual touch-shield! if(ly > 0) lx=1*TP_X; else {lx=0;ly=0;rx=0;ry=0;p=9; } rx=rx+lx; ry=ry+ly; } lx=(rx/8-180)/15; //reduces x-value to 239 max, check for your shield ly=(ry/8-240)/11; //reduces y-value to 319 max, check for your shield if ((ly < 1) || (lx < 1)) {lx=0;ly=0; } } void setup() { unsigned char p; for(p=0;p<20;p++) pinMode(p,OUTPUT); pinMode(SDIN,INPUT); for(p=0; p<90; p++) ts[p]=32; ts[p]='\0'; LCD_Init(); strcpy(pat,"/"); pinMode(DOUT,OUTPUT); if (!SD.begin(10)) strcpy(pat,"NO SD!"); pinMode(DOUT,INPUT); ResetCommandLine(); spistar(); } void loop() { e2=0; GetXYfromTouchcreen(); if ((ly > 0) && (ly<6)) ResetCommandLine(); if (ly > 250) { if (lx<66) { if ((ly>305)) { if (lx<33) { strcat(h5," "); strcat(h8," "); hc=hc++; z5=z5++; } else { ly=269; if (l8<1) strcpy(h8,">LP "); else strcpy(h8,">IT "); if (nm[0]!='\0') {strcat(h8,nm);nm[0]='\0';} } } l8=0; if (ly<266) ShiftKeys(); if ((ly>265) && (ly<281)) { ei=h8[1]; e2=h8[2]; staOcu=0; ConCur(); // strcpy(h4,h8); h6[0]='\0'; l4=4; if ((ei>47) && (ei<58)) l4=5; for (l2=l4;l2<strlen(h8);l2++) h4[l2-l4]=h8[l2]; h4[l2-l4]='\0'; if ((ei>47) && (ei<58) ) { if (strlen(dt)<1) strcpy(h4,"FILE?"); else { h3[0]=ei; h3[1]=e2; h3[2]=h8[3]; h3[3]='\0'; l3=atoi(h3); pinMode(DOUT,OUTPUT); if (strlen(h4)<1) // Delete line no w/o text { ConcatPathWithFileAndNumber(l3); if (SD.exists(h6)) SD.remove(h6); ShowStatus(); strcpy(h4,"OK"); } else { strcpy(h8,h4); if ((l3/2)*2 != l3) // If its an odd line no, first search for the next free one => put it in l2 { l2=l3-1; while (((l3/2)*2 != l3) && (l2<999)) { l2=l2+2; ConcatPathWithFileAndNumber(l2); if (! SD.exists(h6)) l3++; } l4=998; while (l4>98) { ActivityBar(0); ConcatPathWithFileAndNumber(l4-2); if (SD.exists(h6)) { l5=0; ReadFromFile(); f1=0; if ((h4[0]=='G') && (h4[4]>48) && (h4[4]<58) ) { h3[0]=h4[4]; h3[1]=h4[5]; h3[2]=h4[6]; h3[3]='\0'; l6=atoi(h3); if ((l6>=l3) && (l6<l2)) { l6=l6+2; itoa(l6,h3,10); h4[4]=h3[0]; h4[5]=h3[1]; h4[6]=h3[2]; h4[7]='\0'; f1=1; } } if ( (f1==1) || ((l4>l3) && (l4<=l2)) ) { f2=l4; if (( l4<l3) || (l4>l2)) f2=f2-2; ConcatPathWithFileAndNumber(f2); WriteToFile(0); } f2=255; f1=255; } l4=l4-2; } } ConcatPathWithFileAndNumber(l3); strcpy(h4,h8); WriteToFile(0); if (e4==1) { e2=124; l2=atoi(h3); l2=l2+2; itoa(l2,nm,10); ShowStatus(); h4[0]='\0'; } else strcpy(h4,em); } h6[0]='\0'; pinMode(DOUT,INPUT); } } if ((ei=='G') && (e2=='O')) { SendCommandLineToScreen(); if (yc>11) ClearDisplayAndPrintBuffer(); z3=0; x3=0; l3=100; // defines inital line for (l2=0;l2<10;l2++) { v3[l2]=0; c3[l2]=0; c3[l2+10]=0; a3[l2]=0; a3[l2+10]=0; } ConcatPathWithFileAndNumber(4); strcpy(h4,"LOG"); WriteToFile(0); gc=0; hc=0; h5[0]='\0'; h8[0]='\0'; while (ei=='G') { if (actBar) ActivityBar(0); ConcatPathWithFileAndNumber(l3); l3=l3+2; // prepare next line pinMode(DOUT,OUTPUT); if (SD.exists(h6)) { l5=0; ReadFromFile(); h3[0]='\0'; } else {strcat(h3,":?");strcpy(h4,"END");} pinMode(DOUT,INPUT); for (l2=4;l2<strlen(h4);l2++) h6[l2-4]=h4[l2]; h6[l2-4]='\0'; e3=h4[0]; e4=h4[1]; e2=h4[2]; l6=0; // if ((e3=='S') && (e4=='U') && (e2=='T') ) strcpy(h8,h6); // depreceated for space reasons: use SWT & SUW if ((e3=='S') && (e4=='W') && (e2=='T') ) strcpy(h3,h6); // add Text to String W else if (h6[0]=='V') l6=v3[h6[1]-48]; else if (h6[0]=='C') l6=c3[h6[1]-65]; else if (h6[0]=='A') l6=a3[c3[h6[1]-65]]; // convert a,c or v-Variable or integer in 16 byte int else l6=atoi(h6); hf4=1*l6; // save argument as 8 byte int for later purposes l4=e4-48; l5=l4-17; // save as index pointers for register access if ((e3=='J') && (e4=='M') ) // switch to other dir&file with arg=line no. for lib defined in string U, present file name is saved in string U { if (e2=='P') { strcpy(nm,dt); strcpy(h6,pat); strcpy(pat,"/LIB/"); strcat(pat,h8); strcat(pat,"/"); strcpy(dt,h8); strcpy(h8,h6); l3=l6; } else { strcpy(pat,h8); strcpy(dt,nm); l3=l6; } } if (e3=='S') { if (strlen(h5)+strlen(h8)<29) { if ( (e4=='U') && (e2=='W') ) strcat(h8,h5); // concat W to U-String or vice versa if ( (e4=='W') && (e2=='U') ) strcat(h5,h8); } if (e2=='L') v3[l4]=strlen(h5); // String Length of W in v-register if ( (e4=='U')&& (e2=='D') ) h8[0]='\0'; // Delete String U if (e4=='W') { if (e2=='N') itoa(l6,h3,10); // concat numeric to String W if (e2=='D') h5[0]='\0'; // Delete String W if (e2=='R') yc=hf4-1; // Set screen Ror (1-10) for next printing if (e2=='X') x3=hf4*2; // Set screen x-value (0-119) for next printing if (e2=='P') // Print String W in actual line { if ((l6>0) && (l6<6)) sk=l6; SendCommandLineToScreen(); sk=2; if ((yc>10)&&(l6>2)) ClearDisplayAndResetControlVariables(); else if (yc>11) ClearDisplayAndResetControlVariables(); // Reset Screen when line 12 is reached } if (e2=='S') // add String W to file xxx4, if arg is even, string T will we added to file, otherwise its overwritten { if ((l6<10) || (l6>99)) l6=4; hf4=1-l6+(l6/2)*2; ConcatPathWithFileAndNumber(l6); strcpy(h4,h5); WriteToFile(hf4); h3[0]='\0'; } } } if (e3=='D') { if ( (e4=='S') && (e2=='C') ) ClearDisplayAndResetControlVariables(); // Delete SCreen Content (Clear) if ( (e4=='P') && (e2=='X') ) OneColor(2*c3[16],2*c3[17]+y4,2*c3[18],2*c3[19]+y4,l6/256,l6-l6/256);// Draw pixel bLock (x1=CQ, y1=CR, x2=CS, y1=CT, Color=argument) if ( (e4=='L') && (e2=='Y') ) delay(l6); // DeLaY-option in ms if (e2=='P') { if (e4=='O') pinMode(hf4, OUTPUT); // controls input Pin=Argument if ( e4=='I') pinMode(hf4, INPUT); if ( e4=='H') digitalWrite(hf4, HIGH); if ( e4=='L') digitalWrite(hf4, LOW); } if (e2=='R') v3[l4]=digitalRead(hf4); // Digital read pin 'arg' in v-register if (e2=='T') // reads Digital Time since UNO got power; seconds are saved in V-, hours in corresponding C-register { c3[l4]=millis()/3600000; // C-register (0-127 hours) v3[l4]=(millis()-3600000*c3[l4])/1000; // V-register (0-3600 seconds) ! v3[l4+1]=millis()-3600000*c3[l4]-1000*v3[l4]; // V+1-register (0-999 millisecs) ! } if (e2=='G') // Get Digital touch coordinates (0-119) x=> c-register, y=>c+1-register { GetXYfromTouchcreen(); if (ly > 11) { c3[l5]=120-lx/2; // C-register c3[l5+1]=ly/2-6; // C+1-register } } } if (e3=='V') { if (e2=='L') v3[l4]=l3-2; // Save present line in v-register if (e2=='=') v3[l4]=l6; // Self explaining variable operations... if (e2=='+') v3[l4]=v3[l4]+l6; if (e2=='-') v3[l4]=v3[l4]-l6; if (e2=='*') v3[l4]=v3[l4]*l6; if (e2=='/') v3[l4]=v3[l4]/l6; } if (e3=='C') { if (e2=='=') c3[l5]=l6; if (e2=='+') c3[l5]=c3[l5]+l6; if (e2=='-') c3[l5]=c3[l5]-l6; if (e2=='*') c3[l5]=c3[l5]*l6; if (e2=='/') c3[l5]=c3[l5]/l6; } if (e3=='A') { if (e2=='=') a3[c3[l5]]=l6; if (e2=='+') a3[c3[l5]]=a3[c3[l5]]+l6; if (e2=='-') a3[c3[l5]]=a3[c3[l5]]-l6; if (e2=='*') a3[c3[l5]]=a3[c3[l5]]*l6; if (e2=='/') a3[c3[l5]]=a3[c3[l5]]/l6; } if ((e3=='G') && (e4=='T') && (e2=='O') ) l3=l6; // GoTO line in argument (or recalled register!) if ((e3=='G') && (e4=='S') && (e2=='B') ) // GoSuB line in argument (or recalled register!) { if (gc>9) {strcat(h3,em);strcpy(h4,"END");} else { g3[gc]=l3; gc++; l3=l6; } } if ((e3=='R') && (e4=='T') && (e2=='N') ) // ReTurN from subroutine { gc--; if (gc<0) {strcat(h3,":RTE ");strcpy(h4,"END");} else l3=g3[gc]; } if ((e3=='I') && ((e2=='>') || (e2=='=') || (e2=='<'))) // If Vx branch to next GTO-line, else skip next line if ( !( ((e2=='>') && (v3[l4]>l6)) || ( (e2=='=')&& (v3[l4]==l6) ) || ((e2=='<') && (v3[l4]<l6)) ) ) l3=l3+2; if ((e3=='E') && (e4=='N') && (e2=='D') ) ei='X'; // finish execution GetXYfromTouchcreen(); // check if F2 is tapped if ((ly>308)) { if (lx<30) ei='X'; } if (strlen(h5)+strlen(h3)<29) strcat(h5,h3); // really add input to string W if space is available } strcpy(h4,h5); // print 'end' message if available strcpy(h6," "); ActivityBar(1); // h6[0]='\0'; h5[0]='\0'; nm[0]='\0'; x3=0; hc=0; // ly=0; } if ( (ei=='I') && ((e2=='P') || (e2=='T')) && (strlen(dt)>0) ) { pinMode(DOUT,OUTPUT); strcpy(h6,pat); strcat(h6,dt); if (SD.exists(h6)) { l5=0; if ( e2=='T') {l5=atoi(h4);ClearDisplayAndResetControlVariables();} l3=0; while (l3<9) { ActivityBar(0); strcpy(h6,pat); strcat(h6,dt); ReadFromFile(); l3++; if ((h4[0]>48) && (h4[0]<58)&& (e2=='P') && (strlen(h4)>5)) { l3=0; h3[0]=h4[0]; h3[1]=h4[1]; h3[2]=h4[2]; h3[3]='\0'; for (l2=4;l2<strlen(h4);l2++) h4[l2-4]=h4[l2]; h4[l2-4]='\0'; l2=atoi(h3); ConcatPathWithFileAndNumber(l2); WriteToFile(0); } // if ((e2=='T') && (strlen(h4)>0)) if ((e2=='T') && (h4[0]>31)&& (h4[0]<127)) { l3=0; if (strlen(h4)>15) { l6=l6-strlen(h4)+15; if (strlen(h4)<29) l6--; h4[15]='\0'; } strcpy(h5,h4); SendCommandLineToScreen(); if (yc>9) l3=9; } l5=l6; } } l8=0; if (e2=='T') {itoa(l6,nm,10);l2=l6;l8=1;strcpy(h6,"-char#");} else {strcpy(h6,"-line#");ShowStatus();} itoa(l2,h4,10); ActivityBar(1); strcpy(h5,""); hc=0; pinMode(DOUT,INPUT); } if ( ((ei=='X') || (ei=='L')) && (e2=='P') && (strlen(dt)>0) ) { pinMode(DOUT,OUTPUT); l2=atoi(h4); if ( ei=='X') { strcpy(h4,"CODE:"); strcpy(h6,pat); strcat(h6,dt); WriteToFile(0); if (e4==0) ei='L'; } if ( ei=='L') ClearDisplayAndResetControlVariables(); OpenPathAndReadItems(); if (l2 < 100) l2=100; l3=l2; l4=0; while (l3<999) { ActivityBar(0); ConcatPathWithFileAndNumber(l3); strcpy(h5,h3); strcat(h5," "); if (SD.exists(h6)) { l5=0; ReadFromFile(); if ( ei=='X') { strcat(h5,h4); strcpy(h4,h5); strcpy(h6,pat); strcat(h6,dt); WriteToFile(1); if (e4==0) l4++; } else { hc=strlen(h4)+4; if (hc>14) {h4[10]='~';h4[11]='\0';hc=15;l4++;} strcat(h5,h4); SendCommandLineToScreen(); } } l3=l3+2; if (((yc>9) || (yc+2>fc)) && (ei=='L')) {itoa(l3,nm,10);l3=2000;} } pinMode(DOUT,INPUT); ActivityBar(1); hc=0; itoa(l4,h4,10); strcat(h4," ~S"); h5[0]='\0'; h6[0]='\0'; } // 'ED'-cmd depreceated for space reasons: // if (((ei=='H') || (ei=='E')) && ((e2=='D') || (e2=='A'))) if ( (ei=='H') && ((e2=='D') || (e2=='A'))) { l5=0; if ((strlen(h8)>4)&&(ei=='H')) l5=atoi(h4); strcpy(h6,pat); strcat(h6,dt); if (ei=='E') strcat(h6,h4); pinMode(DOUT,OUTPUT); if (SD.exists(h6)) { strcpy(h3,h4); ReadFromFile(); // 'ED'-cmd depreceated for space reasons (Editing lines with <9 chars is more work than retyping): /* if (ei=='E') { strcpy(h8,">"); strcat(h8,h3);strcat(h8," "); if (strlen(h4)>24) h4[24]='\0'; strcat(h8,h4); strcpy(h4,h8); } */ h6[0]='\0'; if (e2=='A') { for (l2=0;l2<strlen(h4);l2++) { if ((h4[l2]>126) || (h4[l2]<32)) { itoa(h4[l2],h3,10); if (strlen(h6)+strlen(h3)+strlen(h4)>28) h4[28-strlen(h6)-strlen(h3)]='\0'; strcat(h6,h3); strcat(h6,":"); } } } } else {strcpy(h6,em);ei='H';} pinMode(DOUT,INPUT); // l5=0; } if ((ei=='F') && (e2=='I')) { strcpy(h6,pat); strcat(h6,dt); pinMode(DOUT,OUTPUT); root = SD.open(h6); if (root) { l4=root.size(); root.close(); itoa(l4,h4,10); } else strcpy(h4,em); pinMode(DOUT,INPUT); strcat(h6,"="); } if ((ei=='M') && (e2=='D')) { if ((strlen(h8)<5)||((strlen(h8)>14))) //RT-11 file name format (9 char) { strcpy(h4,"NAME?"); } else { strcpy(h6,pat); strcat(h6,h4); pinMode(DOUT,OUTPUT); if (SD.mkdir(h6)) { strcpy(pat,h6); strcat(pat,"/"); ShowStatus(); strcpy(h4,"OK"); } else strcpy(h4,em); pinMode(DOUT,INPUT); } h6[0]='\0'; } if ((ei=='O') && (e2=='P')) { if ((strlen(h8)<5)||((strlen(h8)>14))) //RT-11 file name format (6.3) { dt[0]='\0'; ShowStatus(); strcpy(h4,"NAME?"); } else { strcpy(h6,pat); strcat(h6,h4); pinMode(DOUT,OUTPUT); if (SD.exists(h6)) { dt[0]='\0'; strcat(dt,h4); ShowStatus(); strcpy(h4,"OK"); } else { strcpy(dt,h4); strcpy(h4,dt); WriteToFile(0); if (e4==1) { ShowStatus(); strcpy(h4,"NEW"); itoa(100,nm,10); e2=124; } else strcpy(h4,em); } pinMode(DOUT,INPUT); } h6[0]='\0'; } if ((ei=='R') && (e2=='M')) { strcpy(h6,pat); pinMode(DOUT,OUTPUT); if (strlen(dt)>0) { strcat(h6,dt); SD.remove(h6); } else if (strlen(h6)>1) SD.rmdir(h6); if (SD.exists(h6)) strcpy(h4,em); else { if (strlen(dt)>0) dt[0]='\0'; else strcpy(pat,"/"); ShowStatus(); strcpy(h4,"OK"); } pinMode(DOUT,INPUT); h6[0]='\0'; } if ((ei=='L') && (e2=='S')) { l5=0; if (strlen(h4)>0) l5=atoi(h4); ShowStatus(); } if ((ei=='S') && (e2=='B')) { actBar=1-actBar; itoa(actBar,h4,10); } if ((ei=='C') && (e2=='D')) { l5=0; if (strlen(h4)<1) {strcpy(pat,"/");ShowStatus();} else { strcpy(h6,"/"); strcat(h6,h4); strcat(h6,"/"); pinMode(DOUT,OUTPUT); if (SD.exists(h6)) { strcpy(pat,h6); strcpy(h6,":"); ShowStatus(); } else strcpy(h6,em); pinMode(DOUT,INPUT); } } strcat(h6,h4); // depreceated for space reasons: // if (ei!='E') strcat(h6,"}"); // if ((hc+strlen(h6)>14)|| (ei=='E')) strcat(h6,"}"); if (hc+strlen(h6)>14) { strcat(h5,"}"); SaveCommandLineInBuffer(); PrintAsciis(y4+yc*10*sk); yc++; if (yc>11) {ClearDisplayAndPrintBuffer();} z3=0; x3=0; strcpy(h5,h6); if (strlen(h5)>15) { h5[15]='\0'; PrintLineToDisplayAndBuffer(); z3=0; x3=0; h5[0]='\0'; for (l2=15;l2<strlen(h6);l2++) h5[l2-15]=h6[l2]; h5[l2-15]='\0'; } } else { z3=strlen(h5); // if (strlen(h6)+strlen(nm)<1) strcat(h5,"?"); else strcat(h5,":"); strcat(h5,":"); strcat(h5,h6); } // depreceated for space reasons (EDIT is not really needed for lines <9 chars): // if (ei!='E') // { PrintLineToDisplayAndBuffer(); ResetInputControl(); /* } depreceated for space reasons (EDIT is not really needed for lines <9 chars): else { hc=strlen(h5); z5=hc; PrintAsciis(y4+yc*10*sk); lineFeedFlag=0; if (strlen(h6)>15) lineFeedFlag=1; strcpy (h8, h6); } */ } if ((ly>280) && (ly<306)) { if ((hc < 2)&&(lineFeedFlag==0)) errOcu=6; else { staOcu=0; ConCur(); if ((lineFeedFlag>0)&&(hc<1)) { z3=15; z5=15; hc=15; x3=240; y3=y3-10*sk; y2=y3; yc--; lineFeedFlag--; for (l2=0;l2<15;l2++) h5[l2]=ts[15*tc+l2]; tc--; if (tc<0) tc=5; } z3--; z5--; hc--; h5[hc]='\0'; h8[hc+lineFeedFlag*15]='\0'; x3=x3-8*sk; x2=x3; f1=0x00; f2=0x00; digitalWrite(LCD_CS,LOW); PaiRec(0,0,8,9); digitalWrite(LCD_CS,HIGH); f1=0xFF; f2=0xFF; } } } else { if (strlen(h8)<29) { if ((ly>250) && (ly<269)) ei=shiftFlag+32+(240-lx)/16; // read keyboard if ((ly>268) && (ly<291)) ei=shiftFlag+43+(240-lx)/16; if ((ly>290)) ei=shiftFlag+54+(240-lx)/16; if (ei==32) ei=126; // optimize position of some keys if (ei==96) ei=32; if (ei==47) ei=96; if (ei==97) ei=47; h5[hc]=ei; h8[hc+15*lineFeedFlag]=ei; hc++; z5++; h5[hc]='\0'; h8[hc+15*lineFeedFlag]='\0'; } else errOcu=6; } if (yc>11) { ClearDisplayAndPrintBuffer(); ResetInputControl(); x2=0; } staOcu=0; ConCur(); f1=0xFF; f2=0xFF; PrintAsciis(y4+yc*10*sk); if (hc>14) { SaveCommandLineInBuffer(); yc++; lineFeedFlag++; if (yc>11) ClearDisplayAndPrintBuffer(); z5=0; hc=0; z3=0; x3=0; x2=0; h5[0]='\0'; } delay (190); ly=0; } couOcI++; if (couOcI>9) // cursor blink multiplier { couOcI=0; ConCur(); } delay (60); // minimal cursor blink freq, space for slice management }