Coding for small platforms is nearly a lost art OR why I love tiny computers

There was a time when a computer with 4K of memory was something to behold. Indeed, 4K was enough for a BASIC interpreter AND have room left over for user programs. Most I/O was serial, so ALL of that space was for code. The ‘operating system’ was something called a ‘monitor’ or the BASIC itself. Either way, the I/O code was ‘built’ into either the BASIC or the monitor. And, if you had a video terminal, well, you were THE stuff.

Just a few years later, that 4K grew to 16K then 64K and, suddenly, we are talking MEGAbytes. Wow. Well, funny thing happened, code went from small, tight and mostly efficient to BIG, heavy and bloated.  Code in that 4K system that put a character on the screen took, maybe six bytes suddenly took a DLL, which was probably ten times that or more.  Programmers got complacent, including this one.

I recall one job I had, I was maybe 17, that required me to write an accounting screen for a paging system (remember the pocket pager?) I had 2k for the data entry screen AND the billing code. Plus, the datastream to/from the paging system was like 32 bytes.  In that 32 bytes, I had to squeeze in the client number (10 digits), number of pages, and about two dozen status bits and more. I did it. The software went into a dozen or ‘head end’ systems (hey, it was a SMALL market) but it was my first ‘professional’ gig.

My career took me down the Microsoft/Lotus path. I had all kinds of wonders to code with, Visual Studio, Visual Basic, Lotus Notes, web.  My code, while functional and often clever, was sloppy. I forgot what it was to REALLY code.

Well, I had a shot a programming for the Palm Pilot, which reminded me of my old days, but it didn’t last long and I was back to programming for machines with memory measured in the gigabytes.

Imagine my delight when I discovered the world of Microcontrollers.  These things have big capability, but tiny (and I mean tiny) memory spaces. My current microcontroller project, the Adafruit Trinket, based on the ATMel ATtiny85, has 5,2k of available programming memory and 512 BYTES of RAM (as well as 512 bytes of EEPROM.)

Having found some cool 2×16 LCD panels for five bucks each at Radio Shack, these Trinkets and a bunch of parts, I set out to make a game for my step son.  I’m still working on a game concept that will keep his interest, but I did a proof of concept game based on Space Invaders (my all time favorite game.) So, how can one make a Space Invaders on a TWO line by SIXTEEN character display? Well…you need to be creative. AND…you have to fit it, along with a necessary library, into under 5.1K.

So…what did I do? Well, found an old notebook I kept from my TRS-80 days. Looked at some old Tiny Basic game code and…coded.

BSG001First, I needed an idea. The display I am using, from Parallax, allows for eight special characters.  So, I played around with a few designs and one of them looked like the Battlestar Galactica. After some thought, I had the idea: The Galactica’s Viper squadrons are out on patrol. The Galactica was in a fierce battle that has rendered it nearly immovable, it can only hyperjump. It’s turrets are all damaged, save the forward bank, she can only shoot from her forward cannons.  A Cylon has discovered the Galactica and is taking runs at it.  Problem is, the Cylon is jumping randomly, making a direct hit nearly impossible.  If, however, the Galactica does manage to destroy the Cylon, the Galactica then hyperjumps too.  Then, it all happens again.

Cool, huh?IMG_2758

So, I set out to code it. I put code together to read a switch, move a character back and forth and come up with an interrupt mechanism for the button.

Turns out, it was simpler than I thought.  I had some hiccups with the Arduino IDE (which involved upgrading the toolchain, upgrading part of it again, some choice words…) but got them ironed out and, now, the Colonials are fighting the nasty Cylons again.

First, the source code:

#include <SoftwareSerial.h>

SoftwareSerial s(0,2);
 
// globals
int  cylonpos;
int  oldcylonpos;
int  cyDirection;
int  button;
int  posStart;
int  lin2Start;
int  bsgpos;
// special characters
int  bsg;
int  cylon;
 
// the setup routine runs once when you press reset:
void waitforbutton();
void moveCylon();
 
void setup() {  // initialize the digital pin as an output. 
   s.begin(9600);
   s.write(12);
   s.write(17);
   //define the character
   s.write(249);
   s.write(0×4);
   s.write(0xE);
   s.write(0xE);
   s.write(0×15);
   s.write(0x1F);
   s.write(0×15);
   s.write(0xE);
   s.write(0xE);
  
   // baddies
   s.write(251);

   s.write(uint8_t(0×0));//to handle a goofy issue with ’0′
   s.write(uint8_t(0×0));
   s.write(0xE);
   s.write(0×15);
   s.write(0x1F);
   s.write(uint8_t(0×0));
   s.write(uint8_t(0×0));
   s.write(uint8_t(0×0));
  
   pinMode(0,INPUT);
   cyDirection=1;
  
} // the loop routine runs over and over again forever:
void loop() {
  int score;
  score=0;
 
  s.write(12);
  s.println("Shoot the Cylon\n");
  s.println("press btn 2 strt");
 
  waitforbutton();
 
  cylon=3;
  bsg=1;
  lin2Start=148;
  posStart=128;
  randomSeed(analogRead(0)); // gen a random seed
 
  bsgpos = 8;
  cylonpos=random(0,15);
  oldcylonpos=cylonpos;
 
  s.write(12);
  s.write(17);
  s.write(posStart + cylonpos);
 
  s.write(cylon);
  s.write(lin2Start+bsgpos);
  s.write(bsg);
 
  while(1){
    /* Game loop */
    int button;
    s.write(22); // kill the cursor
    moveCylon();
    delay(200);
    button=digitalRead(0);
    if(button==HIGH){
      if(cylonpos==bsgpos){
        s.write(132); // center ‘Hit’ on screen
        s.print("** HIT **");
        score ++;  // update score
        delay(3000);
        s.write(12); // clear screen
        s.write(lin2Start); // move cursor to beginning of line
        s.write("Score:");  // put up score
        s.print(score);
        s.write(lin2Start+bsgpos); // Since we shot the Cylon, we have to leave the sector, so…
        s.write(0×20); // go into hyperdrive and erase the BSG
        bsgpos=random(9,15);  // calculate new position
        s.write(lin2Start+bsgpos); //…and, we are here
        s.write(bsg);
        s.write(posStart+cylonpos);
        s.write(0×20);
        cylonpos=random(0,15); // Damn, they found us!
        oldcylonpos=cylonpos;
        moveCylon();
      }
    } 
  }
}
void moveCylon(){
  // sneaky Cylons…they show up anywhere!
  s.write(posStart+oldcylonpos);
  s.write(0×20);
  if (random(0,6)>3){
      //Cylon warped
      cylonpos=random(0,15);
      oldcylonpos=cylonpos;
  }
 
  cylonpos += cyDirection; // figure out which way to move
  if (cylonpos>15){
   cylonpos=15;
   cyDirection=-1;
  }
 
  if (cylonpos<0){
    cylonpos=0;
    cyDirection=1;
  }
  // erase from old spot
  s.write(posStart+oldcylonpos);
  s.write(0×20);
  s.write(posStart+cylonpos);
  s.write(cylon);
  oldcylonpos=cylonpos;
}

void waitforbutton(){
  SoftwareSerial s(0,1);
 
  int button;
  button=digitalRead(0);
  while(button==LOW){
    button=digitalRead(0);
    delay(1);
  } 
  s.write(1); 
  delay(1000);
  s.write(12);
}

SInce the Trinket is limited, I/O wise, I have only five pins, two of which are shared with the USB programmer and one is shared with the red programming LED, it really limits what you can add. At least, for those of us who are electronically challenged. I have my LCD on pin 2 and the switch on pin 0.  The LCD is controlled with a single line, it also has a five volt line (which goes to the USB power) and ground. The switch is connected to power and a 10k ohm resistor. It connects to pin 0. In the LOOP code, there is a While loop that handles the game logic. Inside the loop, it checks the pin for HIGH, which means the button was pressed. It then checks the position of the BSG and the Cylon. If there is a hit, it tells the user that they hit the Cylon and then increments the score, recalculates the positions and does it all again.  Simple, but kind of hard since the Cylon jumps so much.

While the game is not sophisticated, it does show what you can do in 5K of memory, a limited input mechanism and very limited display.  Now, about the game for my step son…

 

About these ads

4 thoughts on “Coding for small platforms is nearly a lost art OR why I love tiny computers

  1. Pingback: From the Forums: Video Game for the Tricket « adafruit industries blog

  2. Pingback: From the Forums: Video Game for the Tricket | electronics-trade blog

  3. Pingback: “…why I love tiny computers” « adafruit industries blog

  4. Pingback: “…why I love tiny computers” | electronics-trade blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s