Close

01/07/2018 - Using a fast pin library to improve performance

A project log for Sinclair Scientific Calculator Emulator

A register level TMS0805 CPU emulator on an Arduino Nano runs the original 320 instruction calculator program. A custom PCB houses it all.

arduino-enigmaArduino Enigma 03/23/2018 at 02:090 Comments

If you care at all about performance, the Arduino built in pin output function (digitalWrite) is not fast enough. Luckily, many fast IO implementations exist. I am using this one:

https://github.com/mikaelpatel/Arduino-GPIO

https://github.com/mikaelpatel/Arduino-GPIO/blob/master/src/Hardware/AVR/GPIO.h

The pins have to be declared as individual objects, which looks scary at first, but a display function can be created to display any number on any position.

GPIO<BOARD::D5>  SegmentA;
GPIO<BOARD::D8>  SegmentB;
GPIO<BOARD::D10> SegmentC;
GPIO<BOARD::D19> SegmentD;
GPIO<BOARD::D9>  SegmentE;
GPIO<BOARD::D6>  SegmentF;
GPIO<BOARD::D14> SegmentG;
GPIO<BOARD::D18> SegmentDP;

GPIO<BOARD::D2>  Digit1;
GPIO<BOARD::D3>  Digit2;
GPIO<BOARD::D4>  Digit3;
GPIO<BOARD::D17> Digit4;
GPIO<BOARD::D16> Digit5;
GPIO<BOARD::D7>  Digit6;
GPIO<BOARD::D15> Digit7;
GPIO<BOARD::D11> Digit8;
GPIO<BOARD::D12> Digit9;

 The pins are initialized in the following functions:

void allSegmentOutput() {
  SegmentA.output();
  SegmentB.output();
  SegmentC.output();
  SegmentD.output();
  SegmentE.output();
  SegmentF.output();
  SegmentG.output();
  SegmentDP.output();
}

void allSegmentOff() {
  SegmentA.high();
  SegmentB.high();
  SegmentC.high();
  SegmentD.high();
  SegmentE.high();
  SegmentF.high();
  SegmentG.high();
  SegmentDP.high();
}

void allDigitOutput() {
  Digit1.output();
  Digit2.output();
  Digit3.output();
  Digit4.output();
  Digit5.output();
  Digit6.output();
  Digit7.output();
  Digit8.output();
  Digit9.output();
}

void allDigitOff() {
  Digit1.low();
  Digit2.low();
  Digit3.low();
  Digit4.low();
  Digit5.low();
  Digit6.low();
  Digit7.low();
  Digit8.low();
  Digit9.low();
}

 To use them, call outputDigit to put the correct bits for a number in the bus, then call selectDigit to activate the correct anode. 

byte outputDigit(signed char digit, bool decimalpoint = false) {

  byte segmentslit = 0;

  allDigitOff();

  if (decimalpoint)
  {
    segmentslit++;
    SegmentDP.low();
  }
  else
  {
    SegmentDP.high();
  }

  switch (digit) {
    case 0:
      SegmentA.low();
      SegmentB.low();
      SegmentC.low();
      SegmentD.low();
      SegmentE.low();
      SegmentF.low();
      SegmentG.high();
      segmentslit += 6;
      break;
    case 1:
      SegmentA.high();
      SegmentB.low();
      SegmentC.low();
      SegmentD.high();
      SegmentE.high();
      SegmentF.high();
      SegmentG.high();
      segmentslit += 2;
      break;
    case 2:
      SegmentA.low();
      SegmentB.low();
      SegmentC.high();
      SegmentD.low();
      SegmentE.low();
      SegmentF.high();
      SegmentG.low();
      segmentslit += 5;
      break;
    case 3:
      SegmentA.low();
      SegmentB.low();
      SegmentC.low();
      SegmentD.low();
      SegmentE.high();
      SegmentF.high();
      SegmentG.low();
      segmentslit += 5;
      break;
    case 4:
      SegmentA.high();
      SegmentB.low();
      SegmentC.low();
      SegmentD.high();
      SegmentE.high();
      SegmentF.low();
      SegmentG.low();
      segmentslit += 4;
      break;
    case 5:
      SegmentA.low();
      SegmentB.high();
      SegmentC.low();
      SegmentD.low();
      SegmentE.high();
      SegmentF.low();
      SegmentG.low();
      segmentslit += 5;
      break;
    case 6:
      SegmentA.low();
      SegmentB.high();
      SegmentC.low();
      SegmentD.low();
      SegmentE.low();
      SegmentF.low();
      SegmentG.low();
      segmentslit += 6;
      break;
    case 7:
      SegmentA.low();
      SegmentB.low();
      SegmentC.low();
      SegmentD.high();
      SegmentE.high();
      SegmentF.high();
      SegmentG.high();
      segmentslit += 3;
      break;
    case 8:
      SegmentA.low();
      SegmentB.low();
      SegmentC.low();
      SegmentD.low();
      SegmentE.low();
      SegmentF.low();
      SegmentG.low();
      segmentslit += 7;
      break;
    case 9:
      SegmentA.low();
      SegmentB.low();
      SegmentC.low();
      SegmentD.high();
      SegmentE.high();
      SegmentF.low();
      SegmentG.low();
      break;
      segmentslit += 5;
    case 10:
      SegmentA.high();
      SegmentB.high();
      SegmentC.high();
      SegmentD.high();
      SegmentE.high();
      SegmentF.high();
      SegmentG.low();
      segmentslit += 1;
      break;
    case 99:
      SegmentA.high();
      SegmentB.high();
      SegmentC.high();
      SegmentD.high();
      SegmentE.high();
      SegmentF.high();
      SegmentG.high();
      break;
    default:
      allSegmentOff();
      break;
  }

  return segmentslit;
}

byte lastSelectDigit = 0;

void selectDigit(byte digit) {

  lastSelectDigit = digit;

  allDigitOff();
  allDigitInput();

  switch (digit) {
    case 1:
      Digit1.high();
      Digit1.output();
      break;
    case 2:
      Digit2.high();
      Digit2.output();
      break;
    case 3:
      Digit3.high();
      Digit3.output();
      break;
    case 4:
      Digit4.high();
      Digit4.output();
      break;
    case 5:
      Digit5.high();
      Digit5.output();
      break;
    case 6:
      Digit6.high();
      Digit6.output();
      break;
    case 7:
      Digit7.high();
      Digit7.output();
      break;
    case 8:
      Digit8.high();
      Digit8.output();
      break;
    case 9:
      Digit9.high();
      Digit9.output();
      break;
  }
}

Discussions