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

 

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

 

  • 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!