Gordons Projects

--> Projects Top-Level GIT

Added in new C and BASIC programs to drive the Raspberry Ladder
authorGordon Henderson <gordon@pi0.drogon.net>
Mon, 19 Nov 2012 21:30:25 +0000 (21:30 +0000)
committerGordon Henderson <gordon@pi0.drogon.net>
Mon, 19 Nov 2012 21:30:25 +0000 (21:30 +0000)
board

Makefile [new file with mode: 0644]
cylon.c [new file with mode: 0644]
cylon.rtb [new file with mode: 0644]
ladder.c [new file with mode: 0755]
ladderSetup.h [new file with mode: 0755]
reaction.rtb [new file with mode: 0644]
simon.rtb [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..d490772
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,50 @@
+#
+# Makefile:
+#      For the Raspberry Ladder C code.
+#      Copyright (c) 2012 Gordon Henderson
+###############################################################################
+
+#DEBUG = -g -O0
+DEBUG  = -O2
+CC     = gcc
+INCLUDE        = -I/usr/local/include
+CFLAGS = $(DEBUG) -Wall $(INCLUDE) -Winline -pipe
+
+LDFLAGS        = -L/usr/local/lib
+LIBS    = -lwiringPi -lm
+
+SRC    =       ladder.c cylon.c
+
+# May not need to  alter anything below this line
+###############################################################################
+
+OBJ    =       $(SRC:.c=.o)
+
+all:           ladder cylon
+
+ladder:        ladder.o
+       @echo [Link]
+       @$(CC) -o $@ ladder.o $(LDFLAGS) $(LIBS)
+
+cylon: cylon.o
+       @echo [Link]
+       @$(CC) -o $@ cylon.o $(LDFLAGS) $(LIBS)
+
+.c.o:
+       @echo [Compile] $<
+       @$(CC) -c $(CFLAGS) $< -o $@
+
+.PHONEY:       clean
+clean:
+       rm -f $(OBJ) ladder step cylon *~ core tags *.bak
+
+.PHONEY:       tags
+tags:  $(SRC)
+       @echo [ctags]
+       @ctags $(SRC)
+
+.PHONEY:       depend
+depend:
+       makedepend -Y $(SRC)
+
+# DO NOT DELETE
diff --git a/cylon.c b/cylon.c
new file mode 100644 (file)
index 0000000..dcda3d6
--- /dev/null
+++ b/cylon.c
@@ -0,0 +1,88 @@
+
+/*
+ * cylon.c:
+ *     Simple LED sequencer
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include <wiringPi.h>
+
+#include "ladderSetup.h"
+
+// Sequencer data
+//     Triplets of LED, On/Off and delay
+
+uint8_t data [] =
+{
+            0, 1, 1,
+            1, 1, 1,
+  0, 0, 0,  2, 1, 1,
+  1, 0, 0,  3, 1, 1,
+  2, 0, 0,  4, 1, 1,
+  3, 0, 0,  5, 1, 1,
+  4, 0, 0,  6, 1, 1,
+  5, 0, 0,  7, 1, 1,
+  6, 0, 1,
+  7, 0, 1,
+
+  0, 0, 1,     // Extra delay
+
+// Back again
+
+            7, 1, 1,
+            6, 1, 1,
+  7, 0, 0,  5, 1, 1,
+  6, 0, 0,  4, 1, 1,
+  5, 0, 0,  3, 1, 1,
+  4, 0, 0,  2, 1, 1,
+  3, 0, 0,  1, 1, 1,
+  2, 0, 0,  0, 1, 1,
+  1, 0, 1,
+  0, 0, 1,
+
+  0, 0, 1,     // Extra delay
+
+  9, 9, 9,     // End marker
+
+} ;
+
+
+int main (void)
+{
+  int dataPtr ;
+  int l, s, d ;
+
+  printf ("Raspberry Pi cylon sequencer program\n") ;
+
+  if (wiringPiSetup () == -1)
+    exit (1) ;
+
+  raspberryLadderSetup () ;
+
+  dataPtr = 0 ;
+
+  for (;;)
+  {
+    l = data [dataPtr++] ;     // LED
+    s = data [dataPtr++] ;     // State
+    d = data [dataPtr++] ;     // Duration (10ths)
+
+    if ((l + s + d) == 27)
+    {
+      dataPtr = 0 ;
+      continue ;
+    }
+
+    digitalWrite (l, s) ;
+
+    if (digitalRead (BUTTON_A) == 0)   // Pressed as our switch shorts to ground
+      delay (d * 10) ; // Faster!
+    else
+      delay (d * 100) ;
+  }
+
+  return 0 ;
+}
diff --git a/cylon.rtb b/cylon.rtb
new file mode 100644 (file)
index 0000000..6947cad
--- /dev/null
+++ b/cylon.rtb
@@ -0,0 +1,217 @@
+//
+// Flashing Led Technology...
+//     A simple LED sequencer for the Raspbery Ladder board that
+//     puts a "mimic" display on the screen at the same time
+//
+CLS 
+PRINT 
+PRINT "Cylon/Nightrider LED sequencer for the Raspberry Ladder Board"
+PRINT "============================================================="
+PRINT 
+PRINT "Use Button A to make it go 10 times faster,"
+PRINT "    Buttons B & C will light the Red & Green men,"
+PRINT "    and Button D will exit."
+PRINT 
+PRINT "Press the SPACE bar to start: "
+CYCLE 
+REPEAT UNTIL GET$ = " "
+//
+numLEDs = 8 // Big LEDs
+PROC ladderSetup
+PROC setup
+//
+// Read and decode our data
+//
+CYCLE 
+  RESTORE
+  CYCLE 
+    READ l, s, d
+    IF l = -1 THEN BREAK 
+    PROC led(l, s)
+    IF DigitalRead (buttonA) = 0 THEN d = d / 10
+    IF d <> 0 THEN WAIT (d / 100)
+    //
+    IF DigitalRead (buttonB) = 0 THEN 
+      PROC led(gMan, 1)
+    ELSE 
+      PROC led(gMan, 0)
+    ENDIF 
+    //
+    IF DigitalRead (buttonC) = 0 THEN 
+      PROC led(rMan, 1)
+    ELSE 
+      PROC led(rMan, 0)
+    ENDIF 
+    //
+    IF DigitalRead (buttonD) = 0 THEN 
+      PROC tidyUp
+      END 
+    ENDIF 
+    //
+    UPDATE 
+  REPEAT 
+REPEAT 
+END 
+//
+// PROC setup:
+//    Clear the screen and put up the LEDs on the
+//    screen to match those on the ladder board
+//
+DEF PROC setup
+LOCAL i
+HGR 
+COLOUR = Green
+RECT (GWIDTH / 3, 0, GWIDTH / 3, GHEIGHT, TRUE)
+rdius0 = GHEIGHT / (numLEDs * 2) - 18 // Outer
+rdius1 = GHEIGHT / (numLEDs * 2) - 22 // Inner
+manRads0 = rdius0 * 3 / 5
+manRads1 = rdius1 * 3 / 5
+vStep = GHEIGHT / numLEDs
+vOff = vStep / 2
+hPos0 = GWIDTH / 2 // Horizontal middle of the screen
+hPos1 = hPos0 + (hPos0 / 4)
+FOR i = 0 TO numLEDs - 1 CYCLE 
+  PROC led(i, FALSE)
+REPEAT 
+PROC led(8, FALSE)
+PROC led(9, FALSE)
+ENDPROC 
+//
+// tidyUp:
+//    Turn off all the LEDs and exit the program
+//
+DEF PROC tidyUp
+LOCAL i
+// First light everything
+FOR i = 0 TO 9 CYCLE 
+  PROC led(i, 1)
+REPEAT 
+UPDATE 
+WHILE DigitalRead (buttonD) = 0 CYCLE 
+REPEAT 
+//
+FOR i = 0 TO 9 CYCLE 
+  PROC led(i, 0)
+REPEAT 
+UPDATE 
+ENDPROC 
+//
+// PROC led:
+//    Turn an LED on or off on both the screen and
+//    ladder board.
+//
+DEF PROC led(led, state)
+//
+// Ladder board (easy)
+//
+DigitalWrite (led, state)
+//
+// Screen - harder
+//
+SWITCH (led)
+  CASE 0, 1, 9
+    COLOUR = Red
+  ENDCASE 
+  CASE 2, 3
+    COLOUR = Yellow
+  ENDCASE 
+  CASE 4, 5, 8
+    COLOUR = Lime
+  ENDCASE 
+  CASE 6, 7
+    COLOUR = Blue
+  ENDCASE 
+ENDSWITCH 
+//
+IF led <= 7 THEN 
+  //
+  // Big LEDs
+  //
+  CIRCLE (hPos0, GHEIGHT - (vStep * led + vOff), rdius0, TRUE)
+  IF  NOT state THEN  // Turn it OFF
+    COLOUR = Black
+    CIRCLE (hPos0, GHEIGHT - (vStep * led + vOff), rdius1, TRUE)
+  ENDIF 
+ELSE 
+  //
+  // Little LEDs
+  //
+  IF led = 8 THEN  // Green Man
+    CIRCLE (hPos1, GHEIGHT - (vStep * 2 + vOff), manRads0, TRUE)
+    IF  NOT state THEN  // Turn it OFF
+      COLOUR = Black
+      CIRCLE (hPos1, GHEIGHT - (vStep * 2 + vOff), manRads1, TRUE)
+    ENDIF 
+  ELSE  // Red Man
+    CIRCLE (hPos1, GHEIGHT - (vStep * 1 + vOff), manRads0, TRUE)
+    IF  NOT state THEN  // Turn it OFF
+      COLOUR = Black
+      CIRCLE (hPos1, GHEIGHT - (vStep * 1 + vOff), manRads1, TRUE)
+    ENDIF 
+  ENDIF 
+ENDIF 
+ENDPROC 
+//
+// ladderSetup:
+//    This is the setup procedure. We initialise the various
+//    pins into the correct modes and extinbuish all the LEDs
+//
+DEF PROC ladderSetup
+LOCAL i
+FOR i = 0 TO 9 CYCLE 
+  PinMode (i, 1) // Output
+  DigitalWrite (i, 0) // Off
+REPEAT 
+FOR i = 10 TO 13 CYCLE 
+  PinMode (i, 0) // Input
+  PullUpDn (i, 2) // Activate internal pull-up
+REPEAT 
+//
+// Make some globals
+//
+//
+ledRed1 = 0
+ledRed2 = 1
+ledYellow1 = 2
+ledYellow2 = 3
+ledGreen1 = 4
+ledGreen2 = 5
+ledBlue1 = 6
+ledBlue2 = 7
+gMan = 8
+rMan = 9
+buttonA = 11
+buttonB = 10
+buttonC = 12
+buttonD = 13
+//
+ENDPROC 
+//
+// LED Sequence data
+//    Data is read in triplets: L,S,N where L is the LED (1-8), S is the state
+//    1 = on, 0 = off,  and N is the delay time in 100th of seconds.
+//    -1,-1,-1 is end of the sequence.
+//
+DATA 0, 1, 10
+DATA 1, 1, 10
+DATA 0, 0, 0, 2, 1, 10
+DATA 1, 0, 0, 3, 1, 10
+DATA 2, 0, 0, 4, 1, 10
+DATA 3, 0, 0, 5, 1, 10
+DATA 4, 0, 0, 6, 1, 10
+DATA 5, 0, 0, 7, 1, 10
+DATA 6, 0, 10
+DATA 7, 0, 10
+//
+DATA 7, 1, 10
+DATA 6, 1, 10
+DATA 7, 0, 0, 5, 1, 10
+DATA 6, 0, 0, 4, 1, 10
+DATA 5, 0, 0, 3, 1, 10
+DATA 4, 0, 0, 2, 1, 10
+DATA 3, 0, 0, 1, 1, 10
+DATA 2, 0, 0, 0, 1, 10
+DATA 1, 0, 10
+DATA 0, 0, 10
+//
+DATA -1, -1, -1
diff --git a/ladder.c b/ladder.c
new file mode 100755 (executable)
index 0000000..36a1cab
--- /dev/null
+++ b/ladder.c
@@ -0,0 +1,335 @@
+/*
+ * ladder.c:
+ *
+ *     Gordon Henderson, June 2012
+ ***********************************************************************
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <math.h>
+
+#include <wiringPi.h>
+
+#include "ladderSetup.h"
+
+#ifndef        TRUE
+#  define      TRUE    (1==1)
+#  define      FALSE   (1==2)
+#endif
+
+#undef DEBUG
+
+#define        NUM_LEDS         9
+
+
+// Map the LEDs to the hardware pins
+//     using wiringPi pin numbers here
+
+const int ledMap [NUM_LEDS] =
+{
+//  0, 1, 2, 3, 4, 5, 6, 7, 8
+    7, 6, 5, 4, 3, 2, 1, 0, 8
+} ;
+
+
+// Some constants for our circuit simulation
+
+const double vBatt      =      9.0 ;   // Volts (ie. a PP3)
+const double capacitor  =      0.001 ; // 1000uF
+const double rCharge    =   2200.0 ;   // ohms
+const double rDischarge =  68000.0 ;   // ohms
+const double timeInc    =      0.01 ;  // Seconds
+
+double vCharge, vCap, vCapLast ;
+
+
+
+/*
+ * setup:
+ *     Program the GPIO correctly and initialise the lamps
+ ***********************************************************************
+ */
+
+void setup (void)
+{
+  if (geteuid () != 0)
+  {
+    fprintf (stderr, "ladder: Need to be root to run (sudo?)\n") ;
+    exit (0) ;
+  }
+
+  if (wiringPiSetup () == -1)
+    exit (1) ;
+
+  raspberryLadderSetup () ;
+
+// Calculate the actual charging voltage - standard calculation of
+//     vCharge = r2 / (r1 + r2) * vBatt
+//
+//
+//   -----+--- vBatt
+//        |
+//        R1
+//        |
+//        +---+---- vCharge
+//        |   |
+//        R2  C
+//        |   |
+//   -----+---+-----
+
+  vCharge = rDischarge / (rCharge + rDischarge) * vBatt ;
+
+// Start with no charge
+
+  vCap    = vCapLast = 0.0 ;
+}
+
+
+/*
+ * introLeds
+ *     Put a little pattern on the LEDs to start with
+ *********************************************************************************
+ */
+
+void introLeds (void)
+{
+  int i, j ;
+
+
+  printf ("Pi Ladder\n") ;
+  printf ("=========\n\n") ;
+  printf ("       vBatt: %6.2f volts\n", vBatt) ;
+  printf ("     rCharge: %6.0f ohms\n", rCharge) ;
+  printf ("  rDischarge: %6.0f ohms\n", rDischarge) ;
+  printf ("     vCharge: %6.2f volts\n", vCharge) ;
+  printf ("   capacitor: %6.0f uF\n", capacitor * 1000.0) ;
+
+// Flash 3 times:
+
+  for (j = 0 ; j < 3 ; ++j)
+  {
+    for (i = 0 ; i < NUM_LEDS ; ++i)
+      digitalWrite (ledMap [i], 1) ;
+    delay (500) ;
+    for (i = 0 ; i < NUM_LEDS ; ++i)
+      digitalWrite (ledMap [i], 0) ;
+    delay (100) ;
+  }
+
+// All On
+
+  for (i = 0 ; i < NUM_LEDS ; ++i)
+    digitalWrite (ledMap [i], 1) ;
+  delay (500) ;
+
+// Countdown...
+
+  for (i = NUM_LEDS - 1 ; i >= 0 ; --i)
+  {
+    digitalWrite (ledMap [i], 0) ;
+    delay (100) ;
+  }
+  delay (500) ;
+}
+
+
+/*
+ * winningLeds
+ *     Put a little pattern on the LEDs to start with
+ *********************************************************************************
+ */
+
+void winningLeds (void)
+{
+  int i, j ;
+
+// Flash 3 times:
+
+  for (j = 0 ; j < 3 ; ++j)
+  {
+    for (i = 0 ; i < NUM_LEDS ; ++i)
+      digitalWrite (ledMap [i], 1) ;
+    delay (500) ;
+    for (i = 0 ; i < NUM_LEDS ; ++i)
+      digitalWrite (ledMap [i], 0) ;
+    delay (100) ;
+  }
+
+// All On
+
+  for (i = 0 ; i < NUM_LEDS ; ++i)
+    digitalWrite (ledMap [i], 1) ;
+  delay (500) ;
+
+// Countup...
+
+  for (i = 0 ; i < NUM_LEDS ; ++i)
+  {
+    digitalWrite (ledMap [i], 0) ;
+    delay (100) ;
+  }
+  delay (500) ;
+}
+
+
+/*
+ * chargeCapacitor: dischargeCapacitor:
+ *     Add or remove charge to the capacitor.
+ *     Standard capacitor formulae.
+ *********************************************************************************
+ */
+
+void chargeCapacitor (void)
+{
+  vCap = (vCapLast - vCharge) *
+       exp (- timeInc / (rCharge * capacitor)) + vCharge ;
+
+#ifdef DEBUG
+  printf ("+vCap: %7.4f\n", vCap) ;
+#endif
+
+  vCapLast = vCap ;
+}
+
+void dischargeCapacitor (void)
+{
+  vCap = vCapLast *
+       exp (- timeInc / (rDischarge * capacitor)) ;
+
+#ifdef DEBUG
+  printf ("-vCap: %7.4f\n", vCap) ;
+#endif
+
+  vCapLast = vCap ;
+}
+
+
+/*
+ * ledBargraph:
+ *     Output the supplied number as a bargraph on the LEDs
+ *********************************************************************************
+ */
+
+void ledBargraph (double value, int topLedOn)
+{
+  int topLed = (int)floor (value / vCharge * (double)NUM_LEDS) + 1 ;
+  int i ;
+
+  if (topLed > NUM_LEDS)
+    topLed = NUM_LEDS ;
+
+  if (!topLedOn)
+    --topLed ;
+
+  for (i = 0 ; i < topLed ; ++i)
+    digitalWrite (ledMap [i], 1) ;
+
+  for (i = topLed ; i < NUM_LEDS ; ++i)
+    digitalWrite (ledMap [i], 0) ;
+}
+
+
+/*
+ * ledOnAction:
+ *     Make sure the leading LED is on and check the button
+ *********************************************************************************
+ */
+
+void ledOnAction (void)
+{
+  if (digitalRead (BUTTON_A) == LOW)
+  {
+    chargeCapacitor () ;
+    ledBargraph (vCap, TRUE) ;
+  }
+}
+
+
+/*
+ * ledOffAction:
+ *     Make sure the leading LED is off and check the button
+ *********************************************************************************
+ */
+
+void ledOffAction (void)
+{
+  dischargeCapacitor () ;
+
+// Are we still pushing the button?
+
+  if (digitalRead (BUTTON_A) == LOW)
+  {
+    vCap = vCapLast = 0.0 ;
+    ledBargraph (vCap, FALSE) ;
+
+// Wait until we release the button
+
+    while (digitalRead (BUTTON_A) == LOW)
+      delay (10) ;
+  }
+}
+
+
+/*
+ ***********************************************************************
+ * The main program
+ ***********************************************************************
+ */
+
+int main (void)
+{
+  unsigned int then, ledOnTime, ledOffTime ;
+  unsigned int ourDelay = (int)(1000.0 * timeInc) ;
+  
+  setup     () ;
+  introLeds () ;
+
+// Setup the LED times - TODO reduce the ON time as the game progresses
+
+  ledOnTime  = 1000 ;
+  ledOffTime = 1000 ;
+
+// This is our Gate/Squarewave loop
+
+  for (;;)
+  {
+
+// LED ON:
+
+    (void)ledBargraph (vCap, TRUE) ;
+    then = millis () + ledOnTime ;
+    while (millis () < then)
+    {
+      ledOnAction () ;
+      delay       (ourDelay) ;
+    }
+
+// Have we won yet?
+//     We need vCap to be in the top NUM_LEDS of the vCharge
+
+    if (vCap > ((double)(NUM_LEDS - 1) / (double)NUM_LEDS * vCharge))  // Woo hoo!
+    {
+      winningLeds () ;
+      while (digitalRead (BUTTON_A) == HIGH)
+       delay (10) ;
+      while (digitalRead (BUTTON_A) == LOW)
+       delay (10) ;
+      vCap = vCapLast = 0.0 ;
+    }
+
+// LED OFF:
+
+    (void)ledBargraph (vCap, FALSE) ;
+    then = millis () + ledOffTime ;
+    while (millis () < then)
+    {
+      ledOffAction () ;
+      delay        (ourDelay) ;
+    }
+
+  }
+
+  return 0 ;
+}
diff --git a/ladderSetup.h b/ladderSetup.h
new file mode 100755 (executable)
index 0000000..5c07b7b
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * ladderSetup.c:
+ *     Gordon Henderson, November 2012
+ ***********************************************************************
+ */
+
+// Standard raspberryLadder defines
+
+#define        BUTTON_A        11
+#define        BUTTON_B        10
+#define        BUTTON_C        12
+#define        BUTTON_D        13
+
+#define        RED_1           0
+#define        RED_2           1
+#define        YELLOW_1        2
+#define        YELLOW_2        3
+#define        GREEN_1         4
+#define        GREEN_2         5
+#define        BLUE_1          6
+#define        BLUE_2          7
+#define        GREEN_M         8
+#define        RED_M           9
+
+/*
+ * raspberryLadderSetup:
+ *     Initialise the LEDs and Buttons on the Raspberry
+ *     ladder board. Assumes wiringPiSetup has been called!
+ *********************************************************************************
+ */
+
+void raspberryLadderSetup ()
+{
+  int i ;
+
+  for (i = 0 ; i <= 9 ; ++i)
+  {
+    pinMode      (i, OUTPUT) ;
+    digitalWrite (i, LOW) ;
+  }
+
+  for (i = 10 ; i <= 13 ; ++i)
+  {
+    pinMode         (i, INPUT) ;
+    pullUpDnControl (i, PUD_UP) ;
+  }
+
+// Lets leave the Green man ON
+
+  digitalWrite (GREEN_M, HIGH) ;
+}
diff --git a/reaction.rtb b/reaction.rtb
new file mode 100644 (file)
index 0000000..91c6d69
--- /dev/null
@@ -0,0 +1,112 @@
+//
+// reaction:
+//    Reaction timer using the Raspberry Ladder board
+//
+CLS 
+PROC ladderSetup
+NUMFORMAT (5, 3)
+PRINT 
+PRINT "Reaction timer - with the Raspberry Ladder board"
+PRINT "================================================"
+PRINT 
+PRINT "All LEDs will be ON to start."
+PRINT 
+PRINT "Press Button A (The bottom one) to start the count down timer."
+PRINT "At that point the main LEDs will go OFF, leaving the 2 small"
+PRINT "Red & Green LEDs on."
+PRINT 
+PRINT "These will go OFF after a short time, then you need to press"
+PRINT "Button A again."
+PRINT 
+PRINT "For each 50 milliseconds you don't press the button, one of the"
+PRINT "big LEDs will light..."
+PRINT 
+PRINT "Ready when you are..."
+PRINT 
+//
+FOR led = 0 TO 9 CYCLE 
+  DigitalWrite (led, 1)
+REPEAT 
+//
+// Wait for button A, then turn off the main LEDs
+//
+WHILE DigitalRead (buttonA) = 1 CYCLE 
+REPEAT 
+//
+FOR led = 0 TO 7 CYCLE 
+  DigitalWrite (led, 0)
+REPEAT 
+//
+// Wait for it to be released
+//
+WHILE DigitalRead (buttonA) = 0 CYCLE 
+REPEAT 
+//
+// Now wait a random time and turn off the small LEDs
+//
+WAIT (RND (1) * 2 + 1)
+//
+// However if we're pushing the button, we've tried to jump the gun, so ...
+//
+IF DigitalRead (buttonA) = 0 THEN 
+  PRINT "Cheat? Pushed too soon..."
+  END 
+ENDIF 
+//
+DigitalWrite (rMan, 0)
+DigitalWrite (gMan, 0)
+//
+// Go gadget go!
+//
+start = TIME
+CYCLE 
+  IF DigitalRead (buttonA) = 0 THEN BREAK 
+  IF TIME > (start + 50) THEN DigitalWrite (ledBlue2, 1)
+  IF TIME > (start + 100) THEN DigitalWrite (ledBlue1, 1)
+  IF TIME > (start + 150) THEN DigitalWrite (ledGreen2, 1)
+  IF TIME > (start + 200) THEN DigitalWrite (ledGreen1, 1)
+  IF TIME > (start + 250) THEN DigitalWrite (ledYellow2, 1)
+  IF TIME > (start + 300) THEN DigitalWrite (ledYellow1, 1)
+  IF TIME > (start + 350) THEN DigitalWrite (ledRed2, 1)
+  IF TIME > (start + 400) THEN DigitalWrite (ledRed1, 1)
+REPEAT 
+etime = TIME
+PRINT "OK. Count the LEDs... 50ms for each LED lit..."
+PRINT 
+PRINT "But I made it: ";  (etime - start) / 1000;  " seconds."
+END 
+//
+// ladderSetup:
+//    This is the setup procedure. We initialise the various
+//    pins into the correct modes and extinbuish all the LEDs
+//
+DEF PROC ladderSetup
+LOCAL i
+FOR i = 0 TO 9 CYCLE 
+  PinMode (i, 1) // Output
+  DigitalWrite (i, 0) // Off
+REPEAT 
+FOR i = 10 TO 13 CYCLE 
+  PinMode (i, 0) // Input
+  PullUpDn (i, 2) // Activate internal pull-up
+REPEAT 
+//
+// Make some globals
+//
+ledRed1 = 0
+ledRed2 = 1
+ledYellow1 = 2
+ledYellow2 = 3
+ledGreen1 = 4
+ledGreen2 = 5
+ledBlue1 = 6
+ledBlue2 = 7
+gMan = 8
+rMan = 9
+//
+buttonA = 11
+buttonB = 10
+buttonC = 12
+buttonD = 13
+//
+ENDPROC 
diff --git a/simon.rtb b/simon.rtb
new file mode 100644 (file)
index 0000000..bbae9ea
--- /dev/null
+++ b/simon.rtb
@@ -0,0 +1,239 @@
+//
+// simion:
+//    Version of the popular "Simon" memory game for
+//    the Rasberry Ladder board
+//
+PROC ladderSetup
+//
+// 100 memory slots - ought to be enough..
+//
+DIM memory(100)
+//
+CLS 
+PRINT 
+PRINT "==     Simon Says - Remember the LEDs!"
+PRINT "== Memory Game for the Raspberry Ladder Board =="
+PRINT "================================================"
+PRINT 
+PRINT "The Ladder board will flash seuences of LEDs. You must try to"
+PRINT "remember the sequence and push the buttons next to the LEDs"
+PRINT "to confirm your memory. Each cycle, one more LED colour will"
+PRINT "be added to the sequence..."
+//
+CYCLE 
+  memCount = 0
+  userCount = 0
+  lost = FALSE
+  PRINT 
+  PRINT "Push Button A (next to the Blue LEDs) to begin"
+  PRINT 
+  //
+  DigitalWrite (gMan, 0)
+  CYCLE 
+    DigitalWrite (rMan, 1)
+    WAIT (0.1)
+    DigitalWrite (rMan, 0)
+    WAIT (0.1)
+    IF DigitalRead (buttonA) = 0 THEN BREAK 
+  REPEAT 
+  //
+  WAIT (0.01)
+  WHILE DigitalRead (buttonA) = 0 CYCLE 
+    // Wait for button up
+  REPEAT 
+  DigitalWrite (gMan, 1)
+  WAIT (0.5)
+  //
+  // This is it
+  //
+  CYCLE 
+    PROC addNewColour
+    PROC playSequence
+    PROC getInput
+    WAIT (0.5)
+  REPEAT UNTIL lost // We can never win...
+  //
+  PROC mainOff
+  DigitalWrite (rMan, 1)
+  PRINT 
+  PRINT "You ran out of memory!"
+  PRINT "There were ";  memCount;  " changes in the sequence, you got: ";  userCount
+  PRINT "The sequence was:"
+  PRINT 
+  PRINT "   ";  
+  FOR i = 0 TO memCount - 1 CYCLE 
+    led = memory(i)
+    IF led = 0 THEN 
+      TCOLOUR = Blue
+      PRINT "B";  
+    ENDIF 
+    IF led = 1 THEN 
+      TCOLOUR = Green
+      PRINT "G";  
+    ENDIF 
+    IF led = 2 THEN 
+      TCOLOUR = Yellow
+      PRINT "Y";  
+    ENDIF 
+    IF led = 3 THEN 
+      TCOLOUR = Red
+      PRINT "R";  
+    ENDIF 
+    TCOLOUR = White
+    IF i = userCount - 1 THEN 
+      PRINT "<";  
+    ELSE 
+      PRINT " ";  
+    ENDIF 
+  REPEAT 
+  PRINT 
+  PRINT 
+REPEAT 
+END 
+//
+// getInput:
+//    Read the buttons, but if we wait too long, or push the wrong one,
+//    then it's game over!
+//
+DEF PROC getInput
+userCount = 0
+WHILE userCount < memCount CYCLE 
+  button = FN getButton
+  IF button = -1 THEN  // Took too long
+    lost = TRUE
+    BREAK 
+  ENDIF 
+  //
+  // was it the right one?
+  //
+  IF button <> memory(userCount) THEN 
+    PROC lightLED(memory(userCount))
+    lost = TRUE
+    BREAK 
+  ENDIF 
+  //
+  // Light up the light for as long as the button is pushed
+  //
+  PROC lightLED(button)
+  WHILE DigitalRead (buttonA) + DigitalRead (buttonB) + DigitalRead (buttonC) + DigitalRead (buttonD) <> 4 CYCLE 
+  REPEAT 
+  PROC mainOff
+  WAIT (0.05)
+  userCount = userCount + 1
+REPEAT 
+//
+ENDPROC 
+//
+// getButton:
+//    function to return the button pressed - as 0, 1, 2 or 3
+//    or return -1 if we don't push a button inside 2 seconds
+//
+DEF FN getButton
+LOCAL start, button
+etime = TIME + 2000
+button = -1
+CYCLE 
+  IF DigitalRead (buttonA) = 0 THEN button = 0
+  IF DigitalRead (buttonB) = 0 THEN button = 1
+  IF DigitalRead (buttonC) = 0 THEN button = 2
+  IF DigitalRead (buttonD) = 0 THEN button = 3
+REPEAT UNTIL (TIME > etime) OR (button <> -1)
+ = button
+//
+//
+// addNewColour
+//    Add a new colour to the sequence
+//
+DEF PROC addNewColour
+memory(memCount) = RND (4)
+memCount = memCount + 1
+ENDPROC 
+//
+// playSequence:
+//    Play back the sequence stored so-far
+//
+DEF PROC playSequence
+LOCAL i
+FOR i = 0 TO memCount - 1 CYCLE 
+  PROC display(memory(i))
+REPEAT 
+ENDPROC 
+//
+// display:
+//    Light up an LED pair for 1/5 a second
+//
+DEF PROC display(led)
+PROC lightLED(led)
+WAIT (0.4)
+PROC mainOff
+WAIT (0.2)
+ENDPROC 
+//
+// lightLED
+//    Light up the colour pair
+//
+DEF PROC lightLED(ledCol)
+SWITCH (ledCol)
+  CASE 0
+    DigitalWrite (ledBlue1, 1)
+    DigitalWrite (ledBlue2, 1)
+  ENDCASE 
+  CASE 1
+    DigitalWrite (ledGreen1, 1)
+    DigitalWrite (ledGreen2, 1)
+  ENDCASE 
+  CASE 2
+    DigitalWrite (ledYellow1, 1)
+    DigitalWrite (ledYellow2, 1)
+  ENDCASE 
+  CASE 3
+    DigitalWrite (ledRed1, 1)
+    DigitalWrite (ledRed2, 1)
+  ENDCASE 
+ENDSWITCH 
+ENDPROC 
+//
+// mainOff
+//    Turn the main LEDs off
+//
+DEF PROC mainOff
+LOCAL i
+FOR i = 0 TO 7 CYCLE 
+  DigitalWrite (i, 0)
+REPEAT 
+ENDPROC 
+//
+// ladderSetup:
+//    This is the setup procedure. We initialise the various
+//    pins into the correct modes and extinbuish all the LEDs
+//
+DEF PROC ladderSetup
+LOCAL i
+FOR i = 0 TO 9 CYCLE 
+  PinMode (i, 1) // Output
+  DigitalWrite (i, 0) // Off
+REPEAT 
+FOR i = 10 TO 13 CYCLE 
+  PinMode (i, 0) // Input
+  PullUpDn (i, 2) // Activate internal pull-up
+REPEAT 
+//
+// Make some globals
+//
+ledRed1 = 0
+ledRed2 = 1
+ledYellow1 = 2
+ledYellow2 = 3
+ledGreen1 = 4
+ledGreen2 = 5
+ledBlue1 = 6
+ledBlue2 = 7
+gMan = 8
+rMan = 9
+//
+buttonA = 11
+buttonB = 10
+buttonC = 12
+buttonD = 13
+//
+ENDPROC