CLI for Arduino

Go To Last Post
4 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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/...

 

Last Edited: Fri. Nov 23, 2018 - 12:48 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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

 

Click Link: Get Free Stock: Retire early!

share.robinhood.com/jamesc3274

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

oh yes I remember, CP/M+ on my CPC6128 wink

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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!