Port I/O access tool

General discussions related to the Altair 8800 Clone

Port I/O access tool

Postby Wayne Parham » October 28th, 2022, 2:00 pm

I wrote a little program that provides access to the Altair's 256 I/O ports.

It displays the input ports and allows the user to send a byte to any of the output ports.

For example, to send a byte to the console, type "out 11h 41h" which will send an "A" to port 11h.

Just a quick-and-dirty tool, useful when troubleshooting or designing a new board.

You can build it with the Aztec C compiler.

Code: Select all
/* -------------------------------------------------------------------------- */
/* Altair digital I/O Control Panel                                           */
/*                                                                            */
/* Wayne Parham                                                               */
/*                                                                            */
/* wayne@parhamdata.com                                                       */
/* -------------------------------------------------------------------------- */


#include "stdio.h"


int strncasecmp( s1, s2, length )                        /* String comparison */
   char* s1;
   char* s2;
   int length;
{
   char* c1 = s1;
   char* c2 = s2;
   int   l = 0;
   int   r = 0;

   while( (r == 0) && (l < length) && (*c2 != '\0') ) {
      r = *c1 - *c2;
      c1++;
      c2++;
      l++;
   }

   return( r );
}


int hex2decimal( hex )            /* Convert a hex number to a decimal number */
   char* hex;
{
   int decimal = 0;
   int length = 0;
   int value = 0;
   int base = 1;
   int i = 0;

   length = strlen( hex );

   for( i = length--; i >= 0; i-- )
   {
      if( hex[i] >= '0' && hex[i] <= '9' )
      {
         decimal += (hex[i] - 48) * base;
         base *= 16;
      }
      else if( hex[i] >= 'A' && hex[i] <= 'F' )
      {
         decimal += (hex[i] - 55) * base;
         base *= 16;
      }
      else if( hex[i] >= 'a' && hex[i] <= 'f' )
      {
         decimal += (hex[i] - 87) * base;
         base *= 16;
      }
   }

   return( decimal );
}


int interpretNumber( number )         /* Determine if value is decimal or hex */
   char* number;
{
   int lcp;
   int value;
   char lastChar;

   lcp = strlen( number ) - 1; 
   lastChar = number[lcp];

   if( lastChar == 'H' || lastChar == 'h' ) {
      number[lcp] = '\0';
      value = hex2decimal( number );
   } else {
      value = (unsigned char) atoi( number );
   }

   return( value );
}


char* cleanString( string )                      /* Replace  space with  null */
   char* string;                                 /* to isolate first argument */
{
   int p;
   int l;

   l = strlen( string );
   for( p = 0; p < l; p++ ) {
      if( string[p] == ' ' ) {
        string[p] = '\0';
      }
   }

   return( string );
}


void outPort( portdata )                             /* Send data to I/O port */
   char* portdata;
{
   unsigned char port;
   unsigned char data;
   char* op;
   char* dp;

   port   = '\0';
   data   = '\0';

   if( portdata ) {
      op = portdata;
      if ( op ) {
         if( op[0] == ' ' ) {
            op++;                                     /* remove leading space */
         }
         dp = index ( op, ' ' );
         if ( dp ) {
            if( dp[0] == ' ' ) {
               dp++;                                  /* remove leading space */
            }
            op = cleanString( op );
            port = interpretNumber( op );
            data = interpretNumber( dp );
            printf ( "\nPort %d (%02xH) output -> %d (%02xH)\n\n", port, port, data, data );
            out ( port, data );
         } else {
            printf ( "\nInvalid out command\n\n" );
         }
      } else {
         printf ( "\nInvalid out command\n\n" );
      }
   }
}


void clearScreen() {                                       /* Scroll 25 lines */
   int l;
   putchar ( '\r' );
   for ( l = 0; l < 25; l++ ) {
      putchar ( '\n' );
   }
}


int main() {
   unsigned char port;
   unsigned char data;
   unsigned char val;
   int showdata;
   int offset;
   int going;
   int instr;
   int start;
   int end;
   int top;
   int cls;
   int l;
   int v;
   char* pd;
   char cmd[20];

   val    = '\0';
   cmd[0] = '\0';
   showdata = 0;
   going  = 1;
   instr  = 1;
   start  = 0;
   cls    = 1;
   end    = 16;
   top    = 127;
   offset = 0;
   l      = 0;
   v      = 1;

   while ( going ) {

      if ( cls ) {
         clearScreen();
      }

      if ( showdata ) {
         cls = 1;
         puts ("================================= Input Data ==================================");

         while ( start < top ) {

            for ( l = start; l < end; l++ ) {
               data = in( l );
               printf( "P0%02x", l );
               if ( l < (end - 1) ) {
                  printf( " " );
               }
            }
            printf( "\n\r" );

            printf( " " );
            for ( l = start; l < end; l++ ) {
               data = in( l );
               printf( "%02x", data );
               if ( l < (end - 1) ) {
                  printf( "   " );
               }
            }
            printf( "\n\r" );

            start += 16;
            end += 16;
         }
         puts ("===============================================================================");
      }

      if ( instr ) {
         cls = 1;
         puts ("===============================================================================");
         puts ("The  Intel 8080 processor provides 256 addresses for input and output  devices.");
         puts ("This  program  exposes all I/O addresses, allowing you to see the  data  placed");
         puts ("onto  each  of the ports.   You can also send a byte out any of  the  I/O  port");
         puts ("addresses.  Of course, if there is no hardware addressed on a port,  then  data");
         puts ("read will be undetermined.  Data written to an unused port will have no effect.");
         puts ("                                                                               ");
         puts ("Available  commands  are  help, show, view, out  and  quit.   Help  shows  this");
         puts ("message.  Quit ends the program.  Show and view do the same thing, showing  the");
         puts ("top  or bottom 128 input ports.  One argument is expected on the show  or  view");
         puts ("command - either \"high\" or \"low\" - which can be abbreviated.               ");
         puts ("                                                                               ");
         puts ("The  out command requires two arguments, first the port number and second,  the");
         puts ("data  that will be presented to the port.   Both arguments are expected  to  be");
         puts ("one  byte  wide,  e.g. 0 to 255.   Numeric arguments can be either  decimal  or");
         puts ("hexadecimal.   Hex values are indicated by a trailing \"H\" character, which must");
         puts ("be present even if some digits are alpha characters.                           ");
         puts ("===============================================================================");
      }

      printf ("\nCommand:  ");

      fgets ( cmd, sizeof(cmd)-1, stdin );
      cmd[strlen(cmd)-1] = '\0';

      if ( strncasecmp(cmd, "quit", 4) == 0 ) {
         going = 0; 
      }
      else if ( strncasecmp(cmd, "help", 4) == 0 ) {
         showdata = 0;
         instr = 1;
      }
      else if ( strncasecmp(cmd, "show h", 6) == 0 ) {
         showdata = 1;
         instr = 0;
         v = 0;         
      }
      else if ( strncasecmp(cmd, "show l", 6) == 0 ) {
         showdata = 1;
         instr = 0;
         v = 1;         
      }
      else if ( strncasecmp(cmd, "view h", 6) == 0 ) {
         showdata = 1;
         v = 0;         
      }
      else if ( strncasecmp(cmd, "view l", 6) == 0 ) {
         showdata = 1;
         v = 1;         
      }
      else if ( strncasecmp(cmd, "out", 3) == 0 ) {
         showdata = 0;
         instr = 0;
         cls = 0;
         pd = index ( cmd, ' ' );
         outPort( pd );
      }
      if ( v ) {
         start = 0;  /* view bottom 128 input ports */
         end = 16;
         top = 127; 
      } else {       /* view top 128 input ports */
         start = 128;
         end = 144;
         top = 255; 
      }
   }

   puts ("\n\nEnjoy your day!\n\n");

   return 0;
}
Wayne Parham
 
Posts: 240
Joined: March 18th, 2022, 3:01 pm

Re: Port I/O access tool

Postby AltairClone » October 29th, 2022, 1:12 pm

Cool little project!
AltairClone
Site Admin
 
Posts: 632
Joined: April 5th, 2013, 10:55 am


Return to General Discussions

Who is online

Users browsing this forum: No registered users and 16 guests

cron