Those of us old enough to remember the days when micros had monitors and CLIs (perhaps the most famous being CP/M on 8080/Z80?) may appreciate the nostalgia offered to an Arduino by:
https://hackaday.com/2018/11/10/...
Those of us old enough to remember the days when micros had monitors and CLIs (perhaps the most famous being CP/M on 8080/Z80?) may appreciate the nostalgia offered to an Arduino by:
https://hackaday.com/2018/11/10/...
I've not seen one for Arduino, but former freak Bob Gardner often had monitor code in his examples he would post in his ImageCraft code, such as this:
//file monitor32.c //demo monitor routines, read a/d //runs on ere co embmega32 16Mhz 38400 //Jan 18 07 Bob Gardner initial edit #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <math.h> #include <macros.h> //stackcheck #include <iom32v.h> #define INTR_OFF() asm("CLI") #define INTR_ON() asm("SEI") //---ascii equates---------------- #define ESC 0x1b #define CTLQ 0x11 #define CR 0x0d #define LF 0x0a //----externs-------- extern void init_devices(void); //------vars in bss------- unsigned char *pt; unsigned char *pf; unsigned char c; unsigned char dispon; unsigned char passcnt; unsigned char os100ms; unsigned char os1sec; unsigned char gain; unsigned char hr,min,sec; unsigned int addat[8]; //internal 10 bit unsigned int tics,ticsl; int os100msaccum; int os1secaccum; int deltatms; int deltatmsoff; //------rom--------- const unsigned char banner[]={"monitor32 Jan 18 07\n"}; //---------------- void _StackOverflowed(char n){ //called from StackCheck cprintf("overflow! %d\n",n); while(1){}; //hang up } //------------------- void delnms(int n){ //delay n ms int x; while(n--){ x=2600; //empirically determined fudge factor 16 mhz while(x--); } } //------------------------- void initvars(void){ //init vars MCUCSR=0x80; //disable jtag MCUCSR=0x80; } //------RS232------------------- unsigned char kbhit(void){ //return nonzero if char waiting polled version unsigned char b; b=0; if(UCSRA & (1<<RXC)) b=1; return b; } //----------------------- int getchar(void){ //polled version... unsigned char c; while(!kbhit()){}; //wait for char c=UDR; //get char from usart return c; } #if 0 #define RXBUFSIZ 200 unsigned char rxbuf[RXBUFSIZ]; unsigned char rxindx,rxondx; //------------------------- unsigned char kbhit(void){ //return nonzero if char waiting intr version unsigned char b; b=rxindx != rxondx; return b; } //----------------------- int getchar(void){ //intr version... overrides version in library char c; while(!kbhit()){}; //wait for char c=rxbuf[rxondx++]; //get char from rxbuf if(rxondx >= RXBUFSIZ) rxondx=0; return c; } //------------------------------ #pragma interrupt_handler uart0_rx_isr:14 void uart0_rx_isr(void){ //uart has received a character in UDR char c; c=UDR; //get char from usart rxbuf[rxindx++]=c; //put char in rxbuf if(rxindx >= RXBUFSIZ) rxindx=0; } #endif //----------------------- int putc(char c){ //put char to usart0... dont add lf after cr while((UCSRA & 0x20)==0){}; //0x20 is UDRE0. ==0 means data register full UDR=c; //send char return c; } //---------------------- int putchar(char c) { //adds lf after cr if(c=='\n'){ putc('\r'); } putc(c); return c; } //-------------------- void crlf(void){ //send cr lf putchar('\n'); } //------------------ void space(void){ //send space putc(' '); } //------------------ void spaces(char n){ //send n spaces while(n--) space(); } #define ESC 0x1b //---------------------- void gotoxy(int x, int y){ //ansi cursor positioning sequence E[y;xH putc(ESC); putc('['); cprintf("%d",y); putc(';'); cprintf("%d",x); putc('H'); } //---------------------- void clrscr(void){ //clear ansi terminal screen putc(ESC); putc('['); putc('2'); putc('J'); } //------------------ void initscreen(void){ //clear screen and print banner clrscr(); cprintf(banner); } #if 0 //use these with small printf with no modifiers //---------------------- void putnibhex(unsigned char c){ //output bin nib c in hex c+=0x30; //cvt to ascii if(c > 0x39) c+=7; //handle a-f putc(c); } //----------------------- void putbytehex(unsigned char c){ //output c as 2 hex chars unsigned char nib; nib=(c & 0xf0) >>4; putnibhex(nib); nib=c & 0x0f; putnibhex(nib); } //----------------------- void putwordhex(unsigned int w){ //output w as 4 hex chars putbytehex(w >> 8); //hi byte putbytehex(w); //lo byte } #endif //------------------------- unsigned char getche(void){ //get and echo a char from rs232 char c; c=getchar(); putchar(c); return(c); } //------------------------- unsigned char gethex(void){ //return a hex char from rs232 unsigned char b,c; b=0xff; //error return value c=toupper(getche()); if(isxdigit(c)) b=c-0x30; //if c ok, cvt ascii digit to binary if((c>='A') && (c<='F')) b-=7; //if c hexcvt ascii A to binary 10 return(b); } //--------------------------- unsigned char getbyte(void){ //get 2 nibbles, return a binary byte from rs232 unsigned char n1,n2; n1=gethex(); n2=gethex(); return((n1 << 4) + n2); } //---------------------------- unsigned int getaddr(void){ //return addr from rs232 unsigned int th,tl; th=getbyte(); tl=getbyte(); return((th << 8) + tl); } #if 0 //use these to get a number from the console //--------------------- unsigned char getdecdig(void){ //return decimal digit 0..9 from rs232 //return ff (-1) of non hex, like carriage return unsigned char b,c; b=0xff; //error return value c=toupper(getche()); if(isdigit(c)) b=c-0x30; //if c ok, cvt ascii digit to binary return(b); } //----------------------- unsigned char getnum(void){ //return number 0..255 from rs232 -1 to exit char dig,n; dig=getdecdig(); if(dig == -1) return dig; n=dig; // if(n>2) n=2; dig=getdecdig(); if(dig == -1) return dig; n=n*10+dig; // if(n>25) n=25; dig=getdecdig(); if(dig == -1) return dig; n=n*10+dig; if(n>255) n=255; return(n); } #endif #if 0 //uncomment for v6... included in v7 //----------------- void gets(char *p){ //get a string char c; do{ c=getche(); *p++=c; }while(c !=0x0d); p--; //roll p back *p=0x00; //add null over cr } #endif //------debug subs----------- void dump256ram(unsigned char *n){ //dump 16 rows of 16 bytes unsigned char r,c; unsigned char *p, *pa, ch; p=n; crlf(); spaces(6); for(c=0; c<16; c++){ cprintf("%02x ",c); //header if(c==7) space(); } crlf(); crlf(); for(r=0; r<16; r++){ cprintf("%04x ",p); //print addr at beg of line pa=p; //remember p for ascii for(c=0; c<16; c++){ cprintf("%02x ",*p++); //print hex if(c==7) space(); } for(c=0; c<16; c++){ ch=*pa++; if((ch > 0x20) && (ch !=0x0a) && (ch != 0x8a)) //if printing char putc(ch); //print ascii else putc('.'); if(c==7) space(); } crlf(); } } //----------------------- void dump256rom(const unsigned char *n){ //dump 16 rows of 16 bytes unsigned char r,c; const unsigned char *p, *pa; unsigned char ch; p=n; crlf(); spaces(6); for(c=0; c<16; c++){ cprintf("%02x ",c); //header if(c==7) space(); } crlf(); crlf(); for(r=0; r<16; r++){ cprintf("%04x ",p); //print addr at beg of line pa=p; //remember p for ascii for(c=0; c<16; c++){ cprintf("%02x ",*p++); //print hex if(c==7) space(); } for(c=0; c<16; c++){ ch=*pa++; if((ch > 0x20) && (ch !=0x0a) && (ch != 0x8a)) //if printing char putc(ch); //print ascii else putc('.'); if(c==7) space(); } crlf(); } } //------------------ void examineram(void){ //ask for ram mem range and dump unsigned char *from; unsigned char c; cprintf("from:"); from=(unsigned char *)getaddr(); while(c!='q'){ dump256ram(from); cprintf("np or q..."); c=getchar(); if(c=='n') from+=0x100; if(c=='p') from-=0x100; } } //------------------ void examinerom(void){ //ask for rom mem range and dump const unsigned char *from; unsigned char c; cprintf("from:"); from=(const unsigned char *)getaddr(); while(c!='q'){ dump256rom(from); cprintf("np or q..."); c=getchar(); if(c=='n') from+=0x100; if(c=='p') from-=0x100; } } //------------------ void deposit(void){ //ask for addr and data unsigned char *at; unsigned char c; unsigned char nh,nl; cprintf("at:"); at=(unsigned char *)getaddr(); while(1){ cprintf(" %02x ",*at); nh=gethex(); if(nh==0xff) return; nl=gethex(); if(nl==0xff) return; c=((nh << 4) | nl); *at++=c; } } //------------------ void fill(void){ //ask for mem range and fill char and fill unsigned char *from, *to, with; cprintf("from:"); from=(unsigned char *)getaddr(); cprintf(" to:"); to=(unsigned char *)getaddr(); cprintf(" with:"); with=getbyte(); memset(from,with,to-from); } //----------------------------- void (* fn)(void); //fn prototype void dojsr(void){ //ask for addr, jsr to it const unsigned char *to; cprintf(" to:"); to=(const unsigned char *)getaddr(); fn=(void *)to; (*fn)(); //call function fn and returns } //------------------ void debugmenu(void){ //monitor type cmds cprintf("cmds:\n" " e examine ram\n" " c examine rom\n" " d deposit\n" " f fill\n" " j jsr\n" " q quit\n"); } //------------------ void monitorloop(void){ //examine and deposit ram and rom char c; debugmenu(); while(c != 'q'){ crlf(); cprintf("cmd:"); c=getche(); crlf(); switch(c){ case 'e': examineram(); break; case 'c': examinerom(); break; case 'd': deposit(); break; case 'f': fill(); break; case 'j': dojsr(); break; default: debugmenu(); } } } //----end of debug subs---------- const char spindat[4]={'-','\\','/','|'}; char spindex; //------------------ void spin(void){ spindex++; if(spindex > 3) spindex=0; cprintf("%c\r",spindat[spindex]); } #if 0 //----spi--------------------------- char readspi(void){ //return char from spi char cnt,stat; cnt=0; do{ stat=SPSR; cnt++; if(cnt==255){ cprintf("spi rcv timeout "); break; } }while((stat & 0x80)==0); //keep checking until done bit return(SPDR); //clears done flag } //-------------------------- void spiout8(char c){ //send c out spi char cnt,stat; SPDR=c; //send data cnt=0; do{ stat=SPSR; cnt++; if(cnt==255){ cprintf("spi xmt timeout! "); break; } }while((stat & 0x80)==0); } #endif //--------------------- int readadchan(char n){ //read ch n of internal 10 bit a/d //16mhz/128=125000->8usec 125khz a/d clk ADMUX=n; //channel n ADCSRA |=0x40; //init conversion while((ADCSRA & 0x40) !=0){}; //wait for conv complete return ADC; } //-------------------- void readadloop(void){ //read internal 10 bit ad 0-0x3ff 0..1023 char c,n; cprintf("a/d\n"); cprintf("0 1 2 3 4 5 6 7 \n"); c=0; while(c!='q'){ if(kbhit()){ c=getchar(); } for(n=0; n < 8; n++){ addat[n]=readadchan(n); cprintf("%03x ",addat[n]); } cprintf("\r"); } } //--------------------- #pragma interrupt_handler timer0_comp_isr:11 void timer0_comp_isr(void){ //compare occured TCNT0=OCR0 tics++; } //---------------------- void udtime(void){ //read tics, generate oneshots, update hr,min,sec unsigned int tmptics; tmptics=tics; //read copy in case int hits deltatms=tmptics-ticsl; //ms since last pass ticsl=tmptics; //remember last pass os100msaccum+=deltatms; os100ms=0; if(os100msaccum >= 100){ os100ms=1; os100msaccum -= 100; } os1secaccum+=deltatms; //accumulate milliseconds os1sec=0; if(os1secaccum >= 1000){ os1sec=1; os1secaccum -= 1000; } if(os1sec){ sec++; if(sec > 59){ min++; sec=0; if(min > 59){ hr++; min=0; if(hr > 23){ hr=0; }//hr }//min }//sec }//os1sec } //----------------------- void rtloop(void){ //rtloop char c; c=' '; dispon=1; cprintf("running.... q to quit\n"); cprintf("hr:mn:sc a/d mson msof\n"); while(c != 'q'){ //loop forever if(kbhit()){ //if char waiting from pc c=getchar(); //get the char if(c=='p') dispon= !dispon; } udtime(); addat[0]=readadchan(0); if(!dispon) deltatmsoff=deltatms; if(dispon){ // gotoxy(1,15); cprintf("%02d:%02d:%02d %04x %4d %4d\r",hr,min,sec,addat,deltatms,deltatmsoff); delnms(5); } } //while 1 } //-------------------------- void menu(void){ //cmds cprintf("cmds:\n"); cprintf(" a a/ds\n"); cprintf(" c clock\n"); cprintf(" m monitor cmds\n"); } //-------------------------- void mainswitch(unsigned char c){ //parse char from keyboard switch(c){ case 'a': readadloop(); break; case 'm': monitorloop(); break; case 'c': rtloop(); break; default: menu(); } } //----------------- void main(void){ //main program char c; init_devices(); initvars(); initscreen(); //banner while(1){ //main loop menu(); crlf(); putc('>'); //prompt for input c=getche(); crlf(); mainswitch(c); _StackCheck(); } } //---strings embedded in rom-------------- const char copyrightstring[]={"monitor32 computer code\ written by Bob Gardner 407-855-2586 bobgardner@aol.com"}; //--------eof-------------
It reminded me a lot of the rom monitor in my first 6800 based system back in the late 70's.
Jim
oh yes I remember, CP/M+ on my CPC6128
Ah yes, our 6128, I remember when we added the luxury of CP/M 3.0 (aka CP/M+) to the CP/M 2.2 we'd previously been shipping with FD1 and then CPC664 so the TPA increased to 61K using the 128's banked RAM - glory days!