I am a large slow moving vehicle.

Jess is driving right now. We’re in a 2015 Ford F350 six pack long bed towing a 23 foot 1972 Airstream Safari tandem axle trailer. All totaled we’re looking at 60 feet or so in length. We’ve had a running joke talking about the rules for driving a large slow vehicle. We have turned it into a set of chants, almost a mantra.

I am a large slow moving vehicle. I will make slow well indicated lane changes.

I will look all the way to the horizon for things that may need a reaction, for I am slow to stop and not nimble enough to swerve.

I will stay in the right hand lane, for the fast lane is no place for me. Danger and stress and crying are in that lane and I will only use it when I must pass a shower vehicle, and even then only after much contemplation.

I will forgo close in parking spaces and resign myself to walking from the boonies.

I will not turn without ensuring my blinkers have been well and truly blunked, and all other cars know my intentions.

Parking lots are treacherous dangerous confined spaces. I will not attempt to enter a parking lot unless I have an exit strategy already in place.

Those yellow caution signs that everyone else ignores actually carry information meant for me. I shall obey them, there is truth in their words.

I will not yield the right lane nor change speed when you blindly enter the freeway. You are light and nimble and I am a large slow moving vehicle. I’m the rock you must swim around.

I don’t do Drive-Throughs. For my rear end is large and 40 feet behind me.

Hamcation 2023 part 1

Wednesday February 8th, Departure Day

The AC0TG Express all loaded up and ready for the road!

I woke up this morning and busted my butt trying to get kubernetes installed on all the CSS workstations before I left. My fingers were flying through the Ansible scripts and checking that I didn’t mess things up more than I fixed them. I finally got everything squared away around noon and started packing the camper. I already had hooked the camper up to the truck this morning, so mostly it was just getting my clothes and antenna stuff and food loaded up. ShinyBoo and Jess showed up around 2, and Shiny took Dottie to his place for the weekend. Jess and I scrambled around and packed everything up and we were on the road in drizzling rain around 230.

Camping and POTA at Atlanta State Park K-2984

Despite its name, Atlanta State Park is indeed in Texas. The drive in from New Boston, also in Texas, was gorgeous. Towering pine trees lined the road into the park and we drove through the beautiful small Texas town of Maud. While we were stopped waiting for the freight train to pass, Jess and I remarried how nice it would be to live in a city big enough to have a gas station and a Family Dollar. My little town of Campbell only has a gas station, and even that is out by the interstate, not in town.

Jess set up the Buddistick Pro and we had a little trouble keeping it in tune on 40. It would tune up fine, then the swr dip would shift higher, up to ~7.8 MHz. Turns out the 20 Meter coil tap was a little loose or misaligned and was shorting out between two adjacent coil windings and effectively shortening the coil by one turn. Once we had that sorted Jess blasted through 40 SSB contacts in about 30 minutes and then I cranked out 17 CW contacts in about the same 30 minutes. I’m starting to notice I’m catching more and more of each QSO and there were also a few contacts tonight that I caught the whole callsign on the first time. Monday night in CW Academy class Dallas K1DW shotgunned me and Nick with dozens of call signs at 20wpm. I guess it helped.

For dinner Jess made turkey tacos and since we had full water hookups we cleaned the camper up quite a bit. I scrubbed the sinks and countertops and wiped down most of the overhead tambour doors. Then we swept up a huge mound of dirt from the camper floor. Then I mopped the floor with hot water. Who knew 75 square feet of floor could get so dirty. I’m falling back in Love with Miss Daisy again. I want to make some improvements in the way the kitchen counter is laid out and I have some new ideas for storage. I also want to get a dedicated camper Keurig so I can always have coffee on tap.

Nice clean-ish floors!

It’s my bedtime. As I write this, Jess is back there churning away making FT8 contacts and all is well with the world. Tomorrow is going to be a long day of driving.

Thursday February 9th, Driving Day

Jess and I woke up at 545 and got ready for the day. Just a quick breakfast of scrambled eggs and cheese, and a cup of Dunkins Donut Keurig coffee and we were on the road. We covered about 820 miles before we would close our eyes tonight.

We drove pretty much straight through minus a stop for lunch in the sketchy-est Walmart parking lot in the world for lunch in the trailer. We’re talking armed roving full time parking lot security at 12 noon on a Thursday with 2 cop cars parked bracketing the entrance with lights flashing levels of Sketch, Lunch was Bologna and cheese and pickles, paired with a desperately needed Diet Coke for me and a Strawberry and creme Sugar free Dr Pepper for Jess.

Stephen Foster Folk Culture Center State Park, FL K-1919 – We arrived at the park around 11pm after stopping for dinner (letover tacos from last night) in the I-10 Mile Marker 133 rest area in Marianna Florida. We set up the camper and had the buddistick Pro up tuned up and on the air in about 15 minutes. I started with CW tonight and I had my 10 for the activtion in a little over 40 minutes. Jess activated the park using ft8, and we talked until 2am before finally heading to bed.

Stephen Foster Folk Culture Center State Park, FL K-1919

Configuring the AEA PK232MBX for maildrop operation

So after reading Old School Packet Radio you might be wondering how we can use this antiquated piece of hardware for anything useful. Well it might surprise you to find out that the Ham radio packet network and APRS (Automatic Packet Rreporting System) are still using the same protocols today that they were back in the 80’s (for the most part at least).

The biggest problems using this old equipment nowadays seem to be just finding a way to talk over a serial port. Most computers don’t come with serial ports anymore, and most USB to Serial adapters are talking at squeaky little metro-sexual TTL (Transistor-Transistor Logic) voltage levels which are too quiet for our elderly TNC to understand. The PK232MBX wants to speak in “RS232 By God” 12 Volt serial levels, and most USB-Serial adapters just can’t scream loud enough to be heard. You’ll know it’s happening when you are receiving data from the TNC, but no matter how hard you mash the keys, the TNC seems to not be getting your commands. That’s because it is not. If you do happen find a USB adapter that speaks full strength RS232 levels, grab a sharpie and draw a HUGE smiley face on it so you don’t lose it. Otherwise, you need a serial PCI adapter in your computer, or a built in serial port.

It would be really easy for me to get wound up trying to write instructions for getting your TNC and computer talking to each other, but that’s not what we’re here for. So through the magic of the internet … SNAP! you magically have your TNC communicating with your computer in interfaced to your radio. You’re now ready to configure the TNC to act as your ambassador to packet radio universe.

Picture this; you worked and scrimped and saved to scrounge up enough money to finally buy yourself a PK232MBX. After all night wiring serial cables and fiddling with terminal program settings you finally get it talking. What does it have to say? What magic awaits you on the ether of packet radio? Well, this.

AEA PK-232M Data Controller
Copyright (C) 1986-1991 by
Advanced Electronic Applications, Inc.
Release 01.AUG.91

cmd:

Ohhh Kaaaay….. Ummmm. “Help?”

 cmd:help
Help:
AMtor PAcket AScii
ARq Connect BAudot
AList Disconne MOrse
FEc MHeard DISPlay
AChg CStatus CALibrat
NAvtex SIgnal FAx TDm
CONVerse Trans
Xmit Rcve Lock
RESTART RESET
MDCheck TClear
cmd:

Welcome to the 80’s snowflake. When hardware came with instructions, but they were called “Operating Manuals” and they were 266 pages long. They came printed and bound in a gray plastic 3 ring binder that I wish I still had. There was even a rectangular window cut in the cover of the binder that showed the title page of the manual cover underneath. It was glorious!

The good news is that there are really only a few commands between you an Packet radio operation. Namely you need to tell your TNC who you are (MYCALL), what time it is (DAYTIME), how often to announce itself (BEACON), and a few other things that change the way your TNC behaves on air. Here is a list of my normal setup commands along with a little explaination:

  • MYCALL AC0TG – That’s me! My callsign. I’m telling the TNC how it should identify itself to the rest of the world.
  • MYMAIL AC0TG-1 – That’s my mailbox (the MBX portion of PK232MBX). If someone talked to AC0TG, they are talking to me sitting at my keyboard if I am there. If they connect to AC0TG-1 they are talking to the bulletin board system on my TNC. They can leave messages for me to get later.
  • HBAUD 1200 – I’m telling the TNC to ‘speak’ 1200 baud on the radio
  • BEACON EVERY 90 – tell the world that my station exists every 90 (times 10) seconds. Basically sound my barbaric YAWP from the rooftop every 15 minutes.
  • BTEXT AC0TG-1/B Ken in Thornton, CO – Sets my BEACON message
  • DAYTIME 191231163558 – That’s now. Format is YYMMDDHHmmSS. Yep, the year is only 2 digits, not Y2K compliant! This really isn’t needed, your TNC will happily work without knowing what time it is, it just can’t tall you when things happened.
  • 8BITCONV ON – Should the TNC strip the bit 7 from incoming packets. It’s just needed to make things prettier
  • DAYSTAMP ON – when you add a timestamp, include the date.
  • MSTAMP ON – Add timestamps to all monitored packets.
  • CONSTAMP ON – If someone connects to me, tell me when it happened.
  • MAILDROP ON – Turn on my TNCs internal mailbox (BBS)
  • USERS 3 – Max of 3 users can connect to me at the same time
  • MDMON ON – if someone connects to my Mailbox, let me snoop on them.
  • UNPROTO ID VIA AC0KQ – Send my beacons out using the AC0KQ as a digipeater so many more people hear me.

That’s really it. I have all these commands written into a little Linux bash script that sets them all for me at once. I can reset my PK232 to factory defaults and be back on the air in literally 30 seconds or less.

!/bin/bash
printf "MYC AC0TG\rMYMAIL AC0TG-1\rHBAUD 1200\rMDMON ON\rMSTAMP on\r" > /dev/ttyS4
printf "CONSTAMP ON\rDA date +%y%m%d%H%M%S\rDAYS ON\r" > /dev/ttyS4
printf "BEACON EVERY 90\rBTEXT AC0TG-1/B Ken in Thornton, CO DM79\r" > /dev/ttyS4
printf "UNPROTO ID VIA AC0KQ\rMAILDROP ON\rUSERS 3\r" > /dev/ttyS4

So after all this, what do we have? Well assuming the radio is connected and tuned to 145.050 and working correctly, and you live anywhere there is still a few packet radio stations around; after a little while your radio should make this cool “BRAAAAAAPP!” sound and you should start seeing messages (Beacons or traffic) from other stations nearby. You’ll see things like:

01-Jan-19  17:37:37  W6OAV-6>AC0KQ-7*>N0HI-2>KB9KC-7>BEACON:
W6OAV-1/B, W6OAV-7/N 145.05mhz Centennial, CO

This just says that there is a guy out there (W6OAV in Centinial) that has a station and he relayed his BEACON through a few stations. Everybody else out there is hearing my station beaconing “AC0TG-1 Ken in Thornton, CO” every 15 minutes or so. This has all been greatly simplified, but it should get you on the air.

Comma Separated Value Temp/RH logger

I wrote a little utility to log the Temperature and Relative Humidity in my house. The air gets very dry here in Denver, and I want to record a baseline temperature/RH in my house before I invest in a full house humidifier.

It is really pretty simple, using an Arduino Nano, DS3231 Real Time Clock, a micro SD card adapter, and a DHT22 for the sensor. It writes a simple 3 element Comma separated value file with the time in UNIX seconds, the temperature in C, and Relative Humidity percentage.

#include <DHT.h>
#include <TimeLib.h>
#include <TimeAlarms.h>
#include <Wire.h>
#include <DS1307RTC.h>  // a basic DS1307 library that returns time as a time_t
// include the SD library:
#include <SPI.h>
#include <SD.h>

/*
  Takes commands from the serial monitor and returns properly formatted JSON object to Serial monitor

  by Ken Terrell
  12/2018
  v0.1

   DS3231 is at i2c Address 0x68 by default
   AT24C32 is at 0x57 by default

   Connections i2c
   ===============
   Connect SCL to analog 5
   Connect SDA to analog 4
   Connect VDD to 3.3V DC
   Connect GROUND to common ground

   Connections SPI/SD
   ==================
   SD card attached to SPI bus as follows:
   VDD  - 3.3V DC
   MOSI - pin 11 on Arduino Uno/Duemilanove/Diecimila
   MISO - pin 12 on Arduino Uno/Duemilanove/Diecimila
   CLK  - pin 13 on Arduino Uno/Duemilanove/Diecimila
   CS   - pin 10 on Arduino Uno/Duemilanove/Diecimila
   GND  - Common Ground
*/

// Adafruit SD shields and modules: pin 10
const int chipSelect = 10;

#define TIME_HEADER  "T"   // Header tag for serial time sync message

#define DHTPIN 2     // what digital pin we're connected to
// Uncomment whatever type you're using!
//#define DHTTYPE DHT11   // DHT 11
#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321
//#define DHTTYPE DHT21   // DHT 21 (AM2301)
DHT dht(DHTPIN, DHTTYPE);

// Create File object for logfile.csv
File logFile;


void setup()  {
  Serial.begin(115200);
  while (!Serial) ; // wait until Arduino Serial Monitor opens

  Wire.begin();  // Start the I2C interface

  dht.begin(); // STart temp/RH sensor

  displayLogo();
  initRTC();
  initSD();

  Alarm.timerRepeat(60, logCSVReadings);
}

void loop()
{
  switch (Serial.read())
  {
    case 'g':
      showCSVReadings();
      break;
    case 'd':
      dumpCSVReadings();
      break;
    case 'e':
      eraseCSVfile();
      break;
    case 's':
      time_t t = processSyncMessage();
      if (t != 0) {
        RTC.set(t);   // set the RTC and the system time to the received value
        setTime(t);
      }
      break;
    default:
      break;
  }
  Alarm.delay(0); // Service the timers with minimal delay
}

void eraseCSVfile(void) {
  SD.remove("logfile.csv");

  if (SD.exists("logfile.csv")) {
  } else {
    Serial.println("logfile.csv erased.");
  }
}

void showCSVReadings(void) {
  //String jsonString = String(42);
  float temp = dht.readTemperature();
  float RH = dht.readHumidity();

  //jsonString = (String)now() + "," + (String)temp + "," + (String)RH;
  //Serial.println(jsonString);
  Serial.println((String)now() + "," + (String)temp + "," + (String)RH);
}

void dumpCSVReadings(void) {
  // re-open the file for reading:
  logFile = SD.open("logfile.csv");
  if (logFile) {
    Serial.println("logfile.csv:");

    // read from the file until there's nothing else in it:
    while (logFile.available()) {
      Serial.write(logFile.read());
    }
    // close the file:
    logFile.close();
    Serial.println("---");
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening logfile.csv");
  }
}

void logCSVReadings(void) {
  String jsonString = String(42);
  float temp = dht.readTemperature();
  float RH = dht.readHumidity();

  jsonString = (String)now() + "," + (String)temp + "," + (String)RH;
  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  logFile = SD.open("logfile.csv", FILE_WRITE);

  // if the file opened okay, write to it:
  if (logFile) {
    logFile.println(jsonString);
    Serial.println(jsonString);
    // close the file:
    logFile.close();
  } else {
    // if the file didn't open, print an error:
    Serial.println("logCSVReadings() - error opening logfile.csv!");
  }
}

/*  code to process time sync messages from the serial port   */

unsigned long processSyncMessage() {
  unsigned long pctime = 0L;
  const unsigned long DEFAULT_TIME = 1357041600; // Jan 1 2013

  if (Serial.find(TIME_HEADER)) {
    pctime = Serial.parseInt();
    return pctime;
    if ( pctime < DEFAULT_TIME) { // check the value is a valid time (greater than Jan 1 2013)
      pctime = 0L; // return 0 to indicate that the time is not valid
    }
  }
  return pctime;
}

void initRTC(void)
{
  //  Serial.println("------------------------------------");
  //  Serial.println("Attempting to set system time from RTC");
  setSyncProvider(RTC.get);   // the function to get the time from the RTC
  if (timeStatus() != timeSet) {
    Serial.println("Unable to sync with the RTC");
  }
  else {
    Serial.print  ("Current Time: "); Serial.println(now());
  }
  //  Serial.println("------------------------------------");

}

void initSD(void)
{
  //  Serial.println("------------------------------------");
  //  Serial.println("Attempting to initialize SD card interface");
  if (!SD.begin(chipSelect)) {
    Serial.println("initSD() - initialization failed!");
    while (1);
  }
  //  Serial.println("initialization done.");
  //  Serial.println("------------------------------------");

}

void displayLogo(void)
{
  Serial.println("CSVTempRHLogger");
}

Let me know if you find this usefull

Old school packet radio

I’m rolling like we did it back in the 80’s. At the Boulder Amateur Radio Club BARCFest last weekend I found a later model AEA PK232MBX Terminal Node Controller (TNC) for twenty bucks.

For those of us who are wondering what the hell a TNC is and what it does, let me tell you a little story.

Way back in the day before Angry Birds and Instagraph, powerful computers were large, noisy, expensive machines that lived in air conditioned basements under large brick buildings. The kind of computers that a Ham could afford would have had kilobytes ( yes, KILObytes ) of RAM and maybe the only storage medium available was to a standard audio cassette tape. To say the least, their capability was limited.

However, communications over a serial port was one thing that nearly every home computer of the late 70’s to 80’s could do. Even the tiny Timex Sinclair 2048 could manage this feat.

This is were to the TNC steps in. A TNC is essentially a small computer running bulletin board / mail box software. On the local side it is connected via serial cable to the home computer, the remote side is connected to the audio jack of your amateur radio. The radio side of the house is generally referred to as “packet radio” or “packet bbs”.

This, kiddos, is how we rocked it back in the day. 1200 bits per second of pure text hotness (actual speeds were really in the low 100’s of bits/sec).

Replace the ham radio and TNC with a modem and telephone line and you have computer BBS’s. Replace the single BBS with the internet and you have Dialup. Replace the modem and telephone with dedicated internet and you have broadband internet.

Now get off my lawn. 73

HF/VHF/UHF Remote Operating Station

Here is my plan,  I have a 6U rack mount case already and I am planning to build a GoBox out of it.

Front:

All unpopulated rackspace is filled with blanks or vents

3U Blank Panel with cut-outs for:

  • 5″ LCD monitor w/ Raspberry Pi 3 Model B & TNC-Pi
  • 2 Front-firing Speakers (1 each for FT-450d and FT-8900r)

2U Shelf containing:

  • Yaesu FT-450d w/ Microphone and hanger
  • Yaesu FT-450d soundcard interface
  • Yaesu FT-450d PTT footswitch/headset adapter cable
  • Yaesu FT-450d PTT footswitch
  • Yaesu FT-8900r w/ Microphone and hanger
  • Yaesu FT-8900r data connection to TNC-Pi
  • Yaesu FT-8900r remote Microphone input Headset/PTT Footswitch adapter (Needed)

1U Panel with:

  • Lighted [LINE CONNECTED] LED Indicator
  • Lighted [BATT CONNECTED] LED Indicator
  • Lighted [EXT 12V CONNECTED] LED Indicator
  • Lighted [12V POWER] power switch to energize 12V power supply
  • LED voltmeter with momentary push-button switch
  • Dual Anderson PP 12V outputs
  • Powered USB 3.0 bulkhead connected to USB 3.0 HUB

Rear

2U Ventilated Panel

  • (Possible) exhaust fan with LED Switch

3U Blank Panel with:

  • Bulkhead Mains Power [MAINS IN] Fused/Switched – Common mode Chokes
  • Anderson PP [SOLAR/12V IN] – Common mode Chokes
  • Anderson PP [12V OUT] – Common mode Chokes
  • SO-239 HF Antenna – Common mode Chokes
  • SO-239 VHF/UHF Antenna – Common mode Chokes
  • SMA External GPS Antenna – Common mode Chokes

1U Ventilated Panel

Yaesu FT-450d provides

  • HF + 6M DSP 100W transceiver with ATU
  • Full CAT control and programming
  • Headset and PTT Footswitch
  • Provides HF and 6M CW/Phone/Digital/AM/FM
  • 12V supply wiring – Common mode Chokes

Yaesu FT-8900r provides

  • 10M/6M/2M FM 50W, 70cm FM 35W
  • Cross Band Full Duplex
  • Remote Programmable
  • Data connection to TNC-Pi, APRS, KISS
  • 12V supply wiring – Common mode Chokes

Powered USB 3.0 HUB provides

  • Powered from either 12V internal PS or 5V from 12V-5V DC-DC Converter
  • Connected to Front Panel jacks and Raspberry Pi
  • Allows external media and device charging

Raspberry Pi 3 Model B provides

  • Ethernet or WiFi internet connection
  • CAT programming cables for FT-450d and FT-8900r
  • CHIRP for programming radios
  • gpsd for PVT services

 

Getting useful Data from an web4robot i2c LCD into an Arduino

I got the coolest Christmas present ever, and I am finally starting to do something with it!!!

#include <LCDi2cW.h>

#include <WString.h>
#include <Wire.h>

// Doing something slightly useful with the Aduino and my web4robot i2c LCD and 4x4 keypad
// Ken Terrell

#define VERSION "1.2"

#define KEYPAD_BUTTON_1     1
#define KEYPAD_BUTTON_2     2
#define KEYPAD_BUTTON_3     3
#define KEYPAD_BUTTON_A     4
#define KEYPAD_BUTTON_4     5
#define KEYPAD_BUTTON_5     6
#define KEYPAD_BUTTON_6     7
#define KEYPAD_BUTTON_B     8
#define KEYPAD_BUTTON_7     9
#define KEYPAD_BUTTON_8     10
#define KEYPAD_BUTTON_9     11
#define KEYPAD_BUTTON_C     12
#define KEYPAD_BUTTON_STAR  13
#define KEYPAD_BUTTON_0     14
#define KEYPAD_BUTTON_POUND 15
#define KEYPAD_BUTTON_D     16

#define maxLength  8

#define BACKLIGHT  100
#define CONTRAST   50

LCDi2cW lcd = LCDi2cW(4,20,0x4C,0);             // Number of lines and i2c address of the display
 
int Backlight = 0x40;
int Contrast = 0x16;
char SecretCode[] = "1234";
String Guess = String(maxLength);
char charGuess;
int keyInput = 0;
int ledPin = 12;

void setup()
{
  Serial.begin(9600);
  Serial.print("Secret Code Box v");
  Serial.println(VERSION);
  Serial.println("");
  Serial.println("Written by Ken Terrell");
  Serial.println("");

  lcd.init();  // Init the display, clears the display
  lcd.home();
  lcd.clear();
 // delay(50);
  lcd.setBacklight(BACKLIGHT);
//  delay(50);
  lcd.setContrast(CONTRAST);
  pinMode(ledPin, OUTPUT);
  
  setkeypadmode(0);
  resetAll();
  splashscreen();
  mainscreen();
}


void loop()
{
//  charGuess = processKey(); //Get a keypress from the keypad if one is available.

Serial.print("Guess = ");
Serial.println(charGuess);
  if (processKey()) // We got one.
  {
    if (charGuess == 'A')
    { // End of Input, Check Results. Celebrate. Reset. and Redraw main screen.
      if(checkResults()) //checkResults is TRUE if you guessed the secret.
      {
        celebrate();
      }
      resetAll();
      mainscreen();
    }
    else if (Guess.length() < maxLength){
      Guess.concat(charGuess);
      lcd.setCursor(2,Guess.length());
      lcd.print("*");
    }

    while(processKey()) //Now we need to spin our wheels while until the user releases the key.
    { // do nothing in here just waiting on the user.
//       delay(400); // if we need to throttle back the i2c bus usage.
    }
  }
delay(400);
}

int checkResults() //return a 1 if correct, a 0 if incorrect.
{
  lcd.cursor_off();
  lcd.blink_off();
  lcd.clear();
  lcd.print("Your Guess was :");
  lcd.setCursor(1,0);
  lcd.print(Guess);
  lcd.setCursor(2,0);
  if (Guess.equals(SecretCode)){
    lcd.print("Congrats!");
    return(1);
  }
  else {
    lcd.print("Bummer....");
    delay(3000);
    return(0);
  }
}

void celebrate()
{
  for (int i=0; i<10; i++)
  {
    digitalWrite(ledPin, LOW);
    lcd.setBacklight(255);
    digitalWrite(ledPin, HIGH);
    lcd.setBacklight(0);
  }
}

void resetAll() //clear all strings and reset settings back to normal.
{
  Guess = NULL;
  digitalWrite(ledPin, LOW);
  lcd.setBacklight(BACKLIGHT);
  lcd.cursor_off();
  lcd.blink_off();
}  

char processKey() // read character from keypad translate to correct letter and return it.
{
  char pressed;

  int localkey;
  localkey=lcd.keypad();
  switch(localkey){
  case KEYPAD_BUTTON_1:
    pressed = '1';
    break;
  case KEYPAD_BUTTON_2:
    pressed = '2';
    break;
  case KEYPAD_BUTTON_3:
    pressed = '3';
    break;
  case KEYPAD_BUTTON_4:
    pressed = '4';
    break;
  case KEYPAD_BUTTON_5:
    pressed = '5';
    break;
  case KEYPAD_BUTTON_6:
    pressed = '6';
    break;
  case KEYPAD_BUTTON_7:
    pressed = '7';
    break;
  case KEYPAD_BUTTON_8:
    pressed = '8';
    break;
  case KEYPAD_BUTTON_9:
    pressed = '9';
    break;
  case KEYPAD_BUTTON_0:
    pressed = '0';
    break;
  case KEYPAD_BUTTON_A:
    pressed = 'A';
    break;
  case KEYPAD_BUTTON_B:
    pressed = 'B';
    break;
  case KEYPAD_BUTTON_C:
    pressed = 'C';
    break;
  case KEYPAD_BUTTON_D:
    pressed = 'D';
    break;
  case KEYPAD_BUTTON_STAR:
    pressed = '*';
    break;
  case KEYPAD_BUTTON_POUND:
    pressed = '#';
    break;
  }
  return(pressed);
}

int setkeypadmode(int keypadmode) {
//  lcd.keypadMode(keypadmode);
  delay(2);
}

void splashscreen() {
  lcd.setCursor(0,2);
  lcd.print("Keypad Ver ");             // Show Version
  lcd.print(VERSION);
  lcd.setCursor(3,0);
  lcd.print("www.bloomingfool.net");
  lcd.setCursor(1,4);
  lcd.print("Ken Terrell");
  delay(8000);
  lcd.clear();
}

void mainscreen() {
  beeper();
  lcd.clear();
  lcd.print("Enter the Secret!");
  lcd.setCursor(1,0);
  lcd.print("Then press 'A'.");
  lcd.setCursor(2,0);
  lcd.print("> ");
  lcd.cursor_on();
  lcd.blink_on();
  lcd.setCursor(2,1);
}

void beeper()
{
  digitalWrite(ledPin, HIGH);
  delay(50);
  digitalWrite(ledPin, LOW);
  delay(50);
}