Fixed pin numbers and added the last pieces of functionality

--- signalboxes/kelberg/kelberg.ino
+++ signalboxes/kelberg/kelberg.ino
@@ -3,35 +3,35 @@
 #include <Bounce2.h>

 // Red LEDs named after the signal/switch lever/etc they're for.
-// Labeled as a8-a15, so 89-82
-int PIN_LED_SWITCH_5 = 89;  // a8
-int PIN_LED_SWITCH_1 = 88;
-int PIN_LED_SIGNAL_A2 = 87;
-int PIN_LED_SIGNAL_A1 = 86;
-int PIN_LED_SWITCHING_PERMISSION = 85;
-int PIN_LED_ROUTE_A = 84;
-int PIN_LED_ROUTE_BERENBACH = 83;
+// These are the analog ports labeled as a8-a15.
+int PIN_LED_SWITCH_5 = A8;
+int PIN_LED_SWITCH_1 = A9;
+int PIN_LED_SIGNAL_A1 = A10;
+int PIN_LED_SIGNAL_A2 = A11;
+int PIN_LED_SWITCHING_PERMISSION = A12;
+int PIN_LED_ROUTE_A = A13;
+int PIN_LED_ROUTE_BERENBACH = A14;
 // White LED
-int PIN_LED_ROUTE_A_FIXATION = 82;  // a15
+int PIN_LED_ROUTE_A_FIXATION = A15;

 // Levers and lock
-int PIN_LEVER_SWITCH_5 = 78;  // d22
-int PIN_LEVER_SWITCH_1 = 76;  // d24
-int PIN_LEVER_SIGNAL_A2 = 74;  // d26
-int PIN_LEVER_SIGNAL_A1 = 72;  // d28
-int PIN_LOCK_SWITCHING_PERMISSION = 58;  // d32
+int PIN_LEVER_SWITCH_5 = 22;
+int PIN_LEVER_SWITCH_1 = 24;
+int PIN_LEVER_SIGNAL_A1 = 26;
+int PIN_LEVER_SIGNAL_A2 = 28;
+int PIN_LOCK_SWITCHING_PERMISSION = 32;
 // Route levers
-int PIN_LEVER_ROUTE_A1 = 54;  // d36
-int PIN_LEVER_ROUTE_A2 = 50;  // d38
-int PIN_LEVER_ROUTE_BERENBACH1 = 52;  // d40
-int PIN_LEVER_ROUTE_BERENBACH2 = 42;  // d42
+int PIN_LEVER_ROUTE_A1 = 36;
+int PIN_LEVER_ROUTE_A2 = 38;
+int PIN_LEVER_ROUTE_BERENBACH1 = 40;
+int PIN_LEVER_ROUTE_BERENBACH2 = 42;
 // Push button for route fixing
-int PIN_BUTTON_ROUTE_A_FIXATION = 38;  // d46
+int PIN_BUTTON_ROUTE_A_FIXATION = 46;
 // Output pins (pull to 0 means go out of the ground position)
-int PIN_OUTPUT_SWITCH_5 = 6;  // pwm 2 TODO
-int PIN_OUTPUT_SWITCH_1 = 7;  // pwm 3 TODO
-int PIN_OUTPUT_SIGNAL_A1 = 1;  // pwm 4 TODO
-int PIN_OUTPUT_SIGNAL_A2 = 5;  // pwm 5 TODO
+int PIN_OUTPUT_SWITCH_5 = 2;
+int PIN_OUTPUT_SWITCH_1 = 3;
+int PIN_OUTPUT_SIGNAL_A1 = 4;
+int PIN_OUTPUT_SIGNAL_A2 = 5;

 // Array index numbers. These are columns in the locking table.
 int SWITCH_5 = 0;
@@ -215,7 +215,7 @@

 void update_single_lever_led(int pin, int number) {
   if (position_is_ok[number] == false) {
-    if ((millis() % 1000) > 500) {
+    if ((millis() % 500) > 250) {
       digitalWrite(pin, HIGH);
     }
     else {
@@ -231,6 +231,28 @@
     }
   }
 }
+
+
+void update_dual_lever_led(int pin, int number1, int number2) {
+  if (position_is_ok[number1] == false || position_is_ok[number2] == false) {
+    if ((millis() % 500) > 250) {
+      digitalWrite(pin, HIGH);
+    }
+    else {
+      digitalWrite(pin, LOW);
+    }
+  }
+  else {
+    if (movement_allowed(number1) || movement_allowed(number2)) {
+      digitalWrite(pin, LOW);
+    }
+    else {
+      digitalWrite(pin, HIGH);
+    }
+  }
+
+}
+

 void setup() {
@@ -284,7 +306,18 @@
   // Special case: route fixation button should take a second to activate.
   levers[ROUTE_A_FIXATION].interval(1000);

-  // TODO: look up the initial lever positions and update accordingly.
+  // look up the initial lever positions and update accordingly.
+  for (int number = 0; number < ARRAY_SIZE; number++) {
+    levers[number].update();
+
+    if (levers[number].read() == HIGH) {
+      react_to_movement(number, PLUS);
+    }
+    else {
+      react_to_movement(number, MINUS);
+    }
+  }
+
 }

@@ -298,14 +331,22 @@
       react_to_movement(number, MINUS);
     }
   }
-  // TODO: update the LEDs.
+  // Update the LEDs.
   update_single_lever_led(PIN_LED_SWITCH_5, SWITCH_5);
   update_single_lever_led(PIN_LED_SWITCH_1, SWITCH_1);
   update_single_lever_led(PIN_LED_SIGNAL_A1, SIGNAL_A1);
-  update_single_lever_led(13, SIGNAL_A1);
   update_single_lever_led(PIN_LED_SIGNAL_A2, SIGNAL_A2);
   update_single_lever_led(PIN_LED_SWITCHING_PERMISSION, SWITCHING_PERMISSION);
-  // TODO: Update other three leds
+
+  update_dual_lever_led(PIN_LED_ROUTE_A, ROUTE_A1, ROUTE_A2);
+  update_dual_lever_led(PIN_LED_ROUTE_BERENBACH, ROUTE_BERENBACH1, ROUTE_BERENBACH2);
+
+  if (current_position[ROUTE_A_FIXATION] == PLUS) {
+    digitalWrite(PIN_LED_ROUTE_A_FIXATION, LOW);
+  }
+  else {
+    digitalWrite(PIN_LED_ROUTE_A_FIXATION, HIGH);
+  }

   // TODO: update the outgoing pins.
 }


Add more setters

Add more setters


Spelling error, forcing B/C to debug display

--- DigitalVFO.ino
+++ DigitalVFO.ino
@@ -1278,8 +1278,12 @@

   // get state back from EEPROM, set display brightness/contrast
   restore_from_eeprom();
+  LcdContrast = 0;
+  LcdBrightness = 50;
   analogWrite(mc_Brightness, LcdBrightness);
+  Serial.printf(F("Set brightness to %d\n"), LcdBrightness);
   analogWrite(mc_Contrast, LcdContrast);
+  Serial.printf(F("Set contrast to %d\n"), LcdContrast);

   // initialize the display
   lcd.begin(NumCols, NumRows);      // define display size
@@ -1757,7 +1761,7 @@
           display_flash();
           break;
         case vfo_HoldClick:
-          // not saving, restoe original contrast setting
+          // not saving, restore original contrast setting
           LcdContrast = old_contrast;
           analogWrite(mc_Contrast, LcdContrast);
           event_flush();


Menus now working

Menus now working

--- DigitalVFO.ino
+++ DigitalVFO.ino
@@ -24,7 +24,7 @@

 // Digital VFO program name & version
 const char *ProgramName = "DigitalVFO";
-const char *Version = "0.8";
+const char *Version = "0.9";
 const char *Callsign = "vk4fawr";
 const char *Callsign16 = "vk4fawr         ";

@@ -53,9 +53,9 @@
 const byte mc_Contrast = 6;

 // define pins that control the DDS-60
-const byte FQ_UD = 14;    // connected to AD9851 device select pin
-const byte W_CLK = 15;    // connected to AD9851 clock pin
-const byte DATA = 16;     // connected to AD9851 D7 (serial data) pin
+const byte DDS_FQ_UD = 14;    // connected to AD9851 device select pin
+const byte DDS_W_CLK = 15;    // connected to AD9851 clock pin
+const byte DDS_DATA = 16;     // connected to AD9851 D7 (serial data) pin

 // max and min frequency showable
@@ -66,10 +66,9 @@
 #define MAX_FREQ_CHARS  8

 // address in display CGRAM for definable characters
-#define SELECT_CHAR     0   // shows 'underlined' decimal digits (dynamic, 0 to 9)
-#define SPACE_CHAR      1   // shows an 'underlined' space character
-#define ALLSET_CHAR     2   // shows an 'all bits set' character
-// FIXME use only one CGRAM character for 0 to 9 AND space
+#define SELECT_CHAR     0     // shows 'underlined' decimal digits (dynamic, 0 to 9)
+#define SPACE_CHAR      1     // shows an 'underlined' space character
+#define ALLSET_CHAR     0xff  // shows an 'all bits set' character, used for 'bar' display

 // define the numeric digits and space with selection underline
 byte sel0[8] = {0xe,0x11,0x13,0x15,0x19,0x11,0xe,0x1f};
@@ -88,9 +87,6 @@
 byte *sel_digits[] = {sel0, sel1, sel2, sel3, sel4, sel5, sel6, sel7, sel8, sel9, selspace};
 #define SPACE_INDEX   10

-// define custom char for "all bits set"
-byte allset[8] = {0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f};
-
 // map select_offset to bump values
 unsigned long offset2bump[] = {1,           // offset = 0
                                10,          // 1
@@ -136,6 +132,7 @@

 int LcdContrast;
 int LcdBrightness = 255;
+

 ////////////////////////////////////////////////////////////////////////////////
 // Utility routines
@@ -214,6 +211,7 @@
 // display a simple banner on the LCD
 //----------------------------------------

+#ifndef DEBUG
 void banner(void)
 {
   Serial.print(ProgramName); Serial.print(" "); Serial.print(Version);
@@ -241,6 +239,7 @@

   delay(500);
 }
+#endif

 //----------------------------------------
 // Function to convert a Frequency into an array of decimal digit values.
@@ -301,7 +300,7 @@
 ////////////////////////////////////////////////////////////////////////////////

 // handler for selection of an item (vfo_Click event)
-typedef void (*ItemSelection)(Menu *, int);
+typedef void (*ItemAction)(struct Menu *, int);

 // handler for inc/dec of custom item (vfo_RRight, vfo_RLeft events)
 typedef int (*ItemIncDec)(int item_num, int delta);
@@ -310,9 +309,8 @@
 struct MenuItem
 {
   const char *title;          // menu item display text
-  struct Menu *menu;          // menu to use after selection
-  ItemSelection action;       // routine to handle select on the item
-  ItemIncDec incdec;          // routine to handle inc/dec on the item
+  struct Menu *menu;          // if not NULL, menu to pass to show_menu()
+  ItemAction action;          // if not NULL, address of action function
 };

 typedef struct MenuItem *MenuItemPtr;
@@ -325,8 +323,18 @@
   struct MenuItem **items;    // array of pointers to MenuItem data
 };

-typedef struct Menu *MenuPtr;
-
+#ifdef DEBUG
+// dump a MenuItem to the console
+// only called from dump_menu()
+void dump_menuitem(struct MenuItem *menuitem)
+{
+  Serial.print("  menuitem address="); Serial.println((unsigned long) menuitem, HEX);
+  Serial.print("    title="); Serial.println(menuitem->title);
+  Serial.print("    menu="); Serial.println((unsigned long) menuitem->menu, HEX);
+  Serial.print("    action="); Serial.println((unsigned long) menuitem->action, HEX);
+}
+
+// dump a Menu and contained MenuItems to the console
 void dump_menu(const char *msg, struct Menu *menu)
 {
   Serial.println("----------------- Menu --------------------");
@@ -335,20 +343,11 @@
   Serial.print("  title="); Serial.println(menu->title);
   Serial.print("  num_items="); Serial.println(menu->num_items);
   Serial.print("  items address="); Serial.println((unsigned long) menu->items, HEX);
+  for (int i = 0; i < menu->num_items; ++i)
+    dump_menuitem(menu->items[i]);
   Serial.println("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
 }
-
-void dump_menuitem(const char *msg, struct MenuItem *menuitem)
-{
-  Serial.println("--------------- MenuItem ------------------");
-  Serial.println(msg);
-  Serial.print("menuitem address="); Serial.println((unsigned long) menuitem, HEX);
-  Serial.print("  title="); Serial.println(menuitem->title);
-  Serial.print("  menu="); Serial.println((unsigned long) menuitem->menu, HEX);
-  Serial.print("  action="); Serial.println((unsigned long) menuitem->action, HEX);
-  Serial.print("  incdec="); Serial.println((unsigned long) menuitem->incdec, HEX);
-  Serial.println("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
-}
+#endif

 //----------------------------------------
 // Draw the menu on the screen
@@ -364,11 +363,12 @@
 }

 //----------------------------------------
-// Draw a standard menuitem on the screen
+// Draw a standard or custom menuitem on the screen.
 //     menu      pointer to a Menu structure
 //     item_num  the item number to show
 //----------------------------------------
-void menuitem_draw_std(struct Menu *menu, int item_num)
+
+void menuitem_draw(struct Menu *menu, int item_num)
 {
   // figure out max length of item strings
   int max_len = 0;
@@ -386,51 +386,31 @@
   lcd.write(BlankRow);
   lcd.setCursor(NUM_COLS - max_len, 1);
   lcd.write(menu->items[item_num]->title);
-
-}
-
-//----------------------------------------
-// Draw a standard or custom menuitem on the screen.
-//     menu      pointer to a Menu structure
-//     item_num  the item number to show
-// Decides if this is a standard or custom menuitem.
-//----------------------------------------
-
-void menuitem_draw(struct Menu *menu, int item_num)
-{
-  if (menu->num_items == 1)
-    (menu->items[item_num]->incdec)(item_num, 0);  // draw without modifying
-  else
-    menuitem_draw_std(menu, item_num);
 }

 //----------------------------------------
 // Draw a menu page from the passed "menu" structure.
 //     menu      pointer to a defining Menu structure
-//     item_num  number of item to initially display
+//     unused    unused item number (used by action routines)
 // Handle events in the loop here.
-//----------------------------------------
-
-void menu_show(struct Menu *menu, int item_num)
-{
-  //Serial.print("menu_show: menu="); Serial.print((unsigned long) menu, HEX);
+// This code doesn't see events handled in any *_action() routine.
+//----------------------------------------
+
+void menu_show(struct Menu *menu, int unused)
+{
+  int item_num = 0;     // index of the menuitem to show
+
+#ifdef DEBUG
   dump_menu("menu_show, menu:", menu);
-  Serial.print("item_num="); Serial.println(item_num);
+#endif

   // get rid of any stray events to this point
   flush_events();

   // draw the menu page
   menu_draw(menu);
-
-  // decide if drawing menuitem or a dynamic display
-  if (menu->num_items == 1)
-    (menu->items[item_num]->incdec)(item_num, 0);  // draw without modifying
-  else
-    menuitem_draw(menu, item_num);
-
-  Serial.println("Start of menu_show() loop");
-
+  menuitem_draw(menu, item_num);
+
   while (true)
   {
     // handle any pending event
@@ -438,97 +418,52 @@
     {
       // get next event and handle it
       byte event = pop_event();
-      Serial.print("menu_show() loop: event="); Serial.println(event2display(event));
+      Serial.print("menu_show loop: event="); Serial.println(event2display(event));

       switch (event)
       {
         case vfo_RLeft:
-          Serial.println("Menu: vfo_RLeft");
-          if (menu->num_items == 1)
+          Serial.println("menu_show: vfo_RLeft");
+          if (--item_num < 0)
+            item_num = 0;
+          break;
+        case vfo_RRight:
+          Serial.println("menu_show: vfo_RRight");
+          if (++item_num >= menu->num_items)
+            item_num = menu->num_items - 1;
+          break;
+        case vfo_DnRLeft:
+          Serial.println("menu_show: vfo_DnRLeft (ignored)");
+          break;
+        case vfo_DnRRight:
+          Serial.println("menu_show: vfo_DnRRight (ignored)");
+          break;
+        case vfo_Click:
+          if (menu->items[item_num]->action != NULL)
           {
-            // special dynamic menuitem
-            item_num = menu->items[0]->incdec(item_num, -1);
-            Serial.print("After vfo_RLeft, item_num="); Serial.println(item_num);
+            // if there's a handler, call it
+            // this will probably destroy the curent menu page
+            (*menu->items[item_num]->action)(menu, item_num);
           }
           else
           {
-            // normal menuitem
-            if (--item_num < 0)
-              item_num = 0;
+            // recurse down to sub-menu
+            menu_show(menu->items[item_num]->menu, 0);
           }
-          break;
-        case vfo_RRight:
-          Serial.println("Menu: vfo_RRight");
-          if (menu->num_items == 1)
-          {
-            // special dynamic menuitem
-            Serial.print("calling incdec(");
-            Serial.print(item_num);
-            Serial.println(", +1)");
-            item_num = menu->items[0]->incdec(item_num, +1);
-            Serial.print("after vfo_RRight, item_num="); Serial.println(item_num);
-          }
-          else
-          {
-            // normal menuitem
-            if (++item_num >= menu->num_items)
-              item_num = menu->num_items - 1;
-          }
-          Serial.println("point 1");
-          break;
-        case vfo_DnRLeft:
-          Serial.println("Menu: vfo_DnRLeft");
-          break;
-        case vfo_DnRRight:
-          Serial.println("Menu: vfo_DnRRight");
-          break;
-        case vfo_Click:
-          Serial.print("Menu: vfo_Click: menu->title=");
-          Serial.print(menu->title);
-          Serial.print(", item_num=");
-          Serial.print(item_num); Serial.print(", menu->items[item_num]->action=");
-          Serial.println((unsigned long) menu->items[item_num]->action, HEX);
-
-          // if there's a handler, call it
-          // this will probably destroy the curent menu page
-          if (menu->items[0]->action != NULL)
-          {
-            Serial.println("Calling vfo_Click handler");
-            Serial.print("menu->items[0]->action=");
-            Serial.print((unsigned long) menu->items[0]->action, HEX);
-            Serial.print(", item_num="); Serial.println(item_num);
-            (*menu->items[0]->action)(menu->items[0]->menu, item_num);
-          }
-
           menu_draw(menu);    // redraw the menu header
-          Serial.println("Menu: end of vfo_Click handling");
+          Serial.println("menu_show: end of vfo_Click handling");
           break;
         case vfo_HoldClick:
-          Serial.println("Menu: vfo_HoldClick, exit menu");
+          Serial.println("menu_show: vfo_HoldClick, exit menu");
           flush_events();
           return;
         default:
-          Serial.print("Menu: unrecognized event "); Serial.println(event);
+          Serial.print("menu_show: unrecognized event "); Serial.println(event);
           break;
       }
-Serial.println("point 2");

       // update the menu display
-      if (menu->num_items == 1)
-      {
-        Serial.println("point 3");
-        Serial.print("????: item_num="); Serial.print(item_num);
-        Serial.print(", menu->items[0]->incdec=");
-        Serial.println((unsigned long) menu->items[0]->incdec, HEX);
-        (menu->items[0]->incdec)(item_num, 0);  // draw without modifying
-        Serial.println("point 4");
-      }
-      else
-      {
-        Serial.println("point 5");
-        menuitem_draw(menu, item_num);
-        Serial.println("point 6");
-      }
+      menuitem_draw(menu, item_num);
     }
   }
 }
@@ -563,9 +498,6 @@

 void push_event(VFOEvent event)
 {
-  Serial.print("push_event: new event="); Serial.print(event);
-  Serial.print(" = "); Serial.println(event2display(event));
-
   // put new event into next empty slot
   event_queue[queue_fore] = event;

@@ -824,8 +756,11 @@
 // Code to save/restore in EEPROM.
 ////////////////////////////////////////////////////////////////////////////////

+// start storing at address 0
+const int EEPROMBase = 0;
+
 // address for Frequency 'frequency'
-const int AddressFreq = 0;
+const int AddressFreq = EEPROMBase;
 const int AddressFreqSize = sizeof(AddressFreq);

 // address for int 'selected digit'
@@ -861,8 +796,6 @@

 void save_to_eeprom(void)
 {
-  Serial.println("save_to_eeprom() called");
-
   EEPROM.put(AddressFreq, VfoFrequency);
   EEPROM.put(AddressSelDigit, VfoSelectDigit);
   EEPROM.put(AddressBrightness, LcdBrightness);
@@ -900,16 +833,10 @@

 void put_slot(int slot_num, Frequency freq, SelOffset offset)
 {
-  Serial.print("put_slot: slot_num="); Serial.print(slot_num);
-  Serial.print(", freq="); Serial.print(freq);
-  Serial.print(", offset="); Serial.println(offset);
-
   int freq_address = SaveFreqBase + slot_num * SaveFreqSize;
   int offset_address = SaveOffsetBase + slot_num * SaveOffsetSize;

-  Serial.print("Saving freq to slot at "); Serial.println(freq_address);
   EEPROM.put(freq_address, freq);
-  Serial.print("Saving offset to slot at "); Serial.println(offset_address);
   EEPROM.put(offset_address, offset);
 }

@@ -917,6 +844,7 @@
 // print all EEPROM saved data to console
 //----------------------------------------

+#ifdef DEBUG
 void dump_eeprom(void)
 {
   Frequency ulong;
@@ -944,15 +872,7 @@

   Serial.println("=================================================");
 }
-
-//----------------------------------------
-//----------------------------------------
-
-void get_vfo_freq_offset(Frequency &freq, SelOffset &offset)
-{
-  EEPROM.get(AddressFreq, freq);
-  EEPROM.get(AddressSelDigit, offset);
-}
+#endif

 ////////////////////////////////////////////////////////////////////////////////
 // Code to handle the DDS-60
@@ -962,6 +882,7 @@
 ////////////////////////////////////////////////////////////////////////////////

 //----------------------------------------
+// pulse the 'pin' high and then low
 //----------------------------------------

 void dds_pulse_high(byte pin)
@@ -971,15 +892,15 @@
 }

 //----------------------------------------
-// transfer a byte a bit at a time LSB first to DATA
+// transfer a byte a bit at a time, LSB first, to DDS_DATA pin
 //----------------------------------------

 void dds_tfr_byte(byte data)
 {
   for (int i = 0; i < 8; ++i, data >>= 1)
   {
-    digitalWrite(DATA, data & 0x01);
-    dds_pulse_high(W_CLK);
+    digitalWrite(DDS_DATA, data & 0x01);
+    dds_pulse_high(DDS_W_CLK);
   }
 }

@@ -987,38 +908,39 @@
 // frequency of signwave (datasheet page 12) will be <sys clock> * <frequency tuning word> / 2^32
 //----------------------------------------

-void update_dds60(Frequency frequency)
-{
-  int32_t freq = frequency * 4294967296.0 / 180.0e6;
-
-  Serial.print("update_dds60: frequency="); Serial.println(frequency);
-  Serial.print("                   fred="); Serial.println(freq);
+void dds_update(Frequency frequency)
+{
+  int32_t data = frequency * 4294967296.0 / 180.0e6;
+
+  Serial.print("dds_update: frequency="); Serial.println(frequency);
+  Serial.print("                 data="); Serial.println(data);

-  for (int b = 0; b < 4; ++b, freq >>= 8)
-  {
-    dds_tfr_byte(freq & 0xFF);
+  for (int b = 0; b < 4; ++b, data >>= 8)
+  {
+    dds_tfr_byte(data & 0xFF);
   }

   dds_tfr_byte(0x001);
-  dds_pulse_high(FQ_UD);
-}
-
-//----------------------------------------
-//----------------------------------------
-
-void dds_setup()
+  dds_pulse_high(DDS_FQ_UD);
+}
+
+//----------------------------------------
+// initialize the DDS hardware
+//----------------------------------------
+
+void dds_setup(void)
 {
   // all pins to outputs
-  pinMode(FQ_UD, OUTPUT);
-  pinMode(W_CLK, OUTPUT);
-  pinMode(DATA, OUTPUT);
+  pinMode(DDS_FQ_UD, OUTPUT);
+  pinMode(DDS_W_CLK, OUTPUT);
+  pinMode(DDS_DATA, OUTPUT);

   // if your board needs it, connect RESET pin and pulse it to reset AD9851
   // dds_pulse_high(RESET)

   // set serial load enable (Datasheet page 15 Fig. 17)
-  dds_pulse_high(W_CLK);
-  dds_pulse_high(FQ_UD);
+  dds_pulse_high(DDS_W_CLK);
+  dds_pulse_high(DDS_FQ_UD);
 }

@@ -1030,6 +952,7 @@
 // The standard Arduino setup() function.
 //----------------------------------------

+#ifdef RESET
 void zero_slots(void)
 {
   Frequency zero_freq = 0L;
@@ -1048,6 +971,7 @@
     put_slot(i, zero_freq, zero_offset);
   }
 }
+#endif

 void setup(void)
 {
@@ -1063,16 +987,18 @@
   lcd.clear();
   lcd.noCursor();
   lcd.createChar(SPACE_CHAR, sel_digits[SPACE_INDEX]);
-  lcd.createChar(ALLSET_CHAR, allset);

   pinMode(mc_Brightness, OUTPUT);
   pinMode(mc_Contrast, OUTPUT);

-  // get state back from EEPROM
+  // get state back from EEPROM, set display brightness/contrast
   restore_from_eeprom();
   analogWrite(mc_Brightness, LcdBrightness);
   analogWrite(mc_Contrast, LcdContrast);

+  // set up the DDS device
+  dds_setup();
+
   // set up the rotary encoder
   re_setup(VfoSelectDigit);

@@ -1081,13 +1007,20 @@
   banner();
   if (pop_event() == vfo_HoldClick)
   {
+    // if holdClick during banner, reset brightness/contrast
     LcdBrightness = DefaultLcdBrightness;
     analogWrite(mc_Brightness, LcdBrightness);
     LcdContrast = DefaultLcdContrast;
     analogWrite(mc_Contrast, LcdContrast);

-    Serial.print("Reset (not saved) brightness to "); Serial.print(LcdBrightness);
+    Serial.print("Reset brightness to "); Serial.print(LcdBrightness);
     Serial.print(" and contrast to "); Serial.println(LcdContrast);
+
+    lcd.clear();
+    lcd.write("Reset Contrast");
+    lcd.setCursor(0, 1);
+    lcd.write("and Brightness");
+    delay(3000);
   }
 #endif

@@ -1119,95 +1052,14 @@

 //----------------------------------------
 // Define the menu handler routines.
-// These actually do the work, everything else is just navigation.
-//----------------------------------------
-
-// show a save slot, draw in row 1
-void saveslot_show(Menu *menu, int slot_num)
-{
-  Serial.print("saveslot_show() entered, slot_num="); Serial.println(slot_num);
-
-  Frequency freq;
-  SelOffset offset;
-
-  // max length of item strings is "9: xxxxxxxxHz" - 13 chars
-  const int max_len = 13;
-  char buf[MAX_FREQ_CHARS + 1];
+//----------------------------------------
+
+void show_slot_frequency(int slot_num)
+{
+  Frequency freq;         // put data from slot X here
+  SelOffset offset;       // put data from slot X here

   get_slot(slot_num, freq, offset);
-
-  ltochbuff(buf, MAX_FREQ_CHARS, freq);
-  buf[MAX_FREQ_CHARS] = 0;
-
-//  // write menu title on first row
-//  lcd.clear();
-//  lcd.setCursor(0, 0);
-//  lcd.write(menu->title);
-
-  // write indexed item on lower row, right-justified
-  lcd.setCursor(0, 1);
-  lcd.write(BlankRow);
-  // show '*' if slot frequency equal to current
-  if (freq == VfoFrequency)
-  {
-    lcd.setCursor(0, 1);
-    lcd.write("*");
-  }
-  lcd.setCursor(NUM_COLS - max_len, 1);
-  lcd.write(slot_num + '0');
-  lcd.write(": ");
-  lcd.write(buf);
-  lcd.write("Hz");
-}
-
-//----------------------------------------
-// save the current frequency to a slot
-//----------------------------------------
-
-void saveslot_action(Menu *menu, int item_num)
-{
-  Serial.print("saveslot_action() entered, item_num=");
-  Serial.println(item_num);
-
-  // display an 'action' flash
-  menu_flash();
-
-  put_slot(item_num, VfoFrequency, VfoSelectDigit);
-
-//  savresdel_show(menu, item_num);
-}
-
-//----------------------------------------
-// cycle through the save slots
-//----------------------------------------
-
-int saveslot_incdec(int item_num, int delta)
-{
-  Frequency freq;
-  SelOffset offset;
-
-  Serial.print("saveslot_incdec: item_num="); Serial.print(item_num);
-  Serial.print(", delta="); Serial.println(delta);
-
-  if (delta != 0)
-  {
-    Serial.print("Old item_num="); Serial.println(item_num);
-
-    // bump the slot number, limit to [0, 9]
-    item_num += delta;
-    if (item_num < 0)
-      item_num = 0;
-    else
-      if (item_num > 9)
-        item_num = 9;
-
-    Serial.print("New item_num="); Serial.println(item_num);
-  }
-
-  // draw the row 1 representation of the value
-  Serial.println("Xpoint 1");
-  get_slot(item_num, freq, offset);
-  Serial.println("Xpoint 2");
   lcd.setCursor(0, 1);
   lcd.write(BlankRow);
   if (VfoFrequency == freq)
@@ -1215,363 +1067,339 @@
     lcd.setCursor(0, 1);
     lcd.write("*");
   }
-  Serial.println("Xpoint 3");
   lcd.setCursor(4, 1);
-  lcd.write(item_num + '0');
+  lcd.write(slot_num + '0');
   lcd.write(":");
-  Serial.println("Xpoint 4");
   print_freq(freq, -1, 1);
-  Serial.println("Xpoint 5");
-
-  Serial.print("saveslot_incdec: returning item_num="); Serial.println(item_num);
-  return item_num;
+}
+
+//----------------------------------------
+// save the current frequency to a slot.
+//   menu      address of 'calling' menu
+//   item_num  index of MenuItem we were actioned from
+//----------------------------------------
+
+void saveslot_action(struct Menu *menu, int item_num)
+{
+  int slot_num = 0;       // the slot we are viewing/saving
+
+  // get rid of any stray events to this point
+  flush_events();
+
+  // draw row 0 of menu
+  lcd.clear();
+  lcd.write(menu->items[item_num]->title);
+
+  // show row slot info on row 1
+  show_slot_frequency(slot_num);
+
+  // handle events in our own little event loop
+  while (true)
+  {
+    // handle any pending event
+    if (events_pending() > 0)
+    {
+      byte event = pop_event(); // get next event and handle it
+
+      switch (event)
+      {
+        case vfo_RLeft:
+          if (--slot_num < 0)
+            slot_num = 0;
+          break;
+        case vfo_RRight:
+          if (++slot_num >= NumSaveSlots)
+            slot_num = NumSaveSlots - 1;
+          break;
+        case vfo_Click:
+          put_slot(slot_num, VfoFrequency, VfoSelectDigit);
+          show_slot_frequency(slot_num);
+          menu_flash();
+          break;
+        case vfo_HoldClick:
+          flush_events();
+          return;
+        default:
+          // ignore any events we don't handle
+          break;
+      }
+
+      // show row slot info
+      show_slot_frequency(slot_num);
+    }
+  }
 }

 //----------------------------------------
 // restore the current frequency from a slot
-//----------------------------------------
-
-void restoreslot_action(Menu *menu, int item_num)
-{
-  Serial.println("restoreslot_show() entered");
-
-  // display an 'action' flash
-  menu_flash();
-
-  get_slot(item_num, VfoFrequency, VfoSelectDigit);
-
-  savresdel_show(menu, item_num);
-}
-
-//----------------------------------------
-// cycle through the slots
-//----------------------------------------
-
-int restoreslot_incdec(int item_num, int delta)
-{
-  return item_num;
+//   menu      address of 'calling' menu
+//   item_num  index of MenuItem we were actioned from
+//----------------------------------------
+
+void restoreslot_action(struct Menu *menu, int item_num)
+{
+  int slot_num = 0;       // the slot we are viewing/restoring
+
+  // get rid of any stray events to this point
+  flush_events();
+
+  // draw row 0 of menu
+  lcd.clear();
+  lcd.write(menu->items[item_num]->title);
+
+  // show row slot info on row 1
+  show_slot_frequency(slot_num);
+
+  // handle events in our own little event loop
+  while (true)
+  {
+    // handle any pending event
+    if (events_pending() > 0)
+    {
+      byte event = pop_event(); // get next event and handle it
+
+      switch (event)
+      {
+        case vfo_RLeft:
+          if (--slot_num < 0)
+            slot_num = 0;
+          break;
+        case vfo_RRight:
+          if (++slot_num >= NumSaveSlots)
+            slot_num = NumSaveSlots - 1;
+          break;
+        case vfo_Click:
+          get_slot(slot_num, VfoFrequency, VfoSelectDigit);
+          menu_flash();
+          break;
+        case vfo_HoldClick:
+          flush_events();
+          return;
+        default:
+          // ignore any events we don't handle
+          break;
+      }
+
+      // show row slot info
+      show_slot_frequency(slot_num);
+    }
+  }
 }

 //----------------------------------------
 // delete the frequency in a slot
-//----------------------------------------
-
-void deleteslot_action(Menu *menu, int item_num)
-{
-  Serial.println("deleteslot_show() entered");
-
-  // display an 'action' flash
-  menu_flash();
-
-  put_slot(item_num, 0L, 0);
-
-  savresdel_show(menu, item_num);
-}
-
-//----------------------------------------
-// cycle through the slots
-//----------------------------------------
-
-int deleteslot_incdec(int item_num, int delta)
-{
-  Frequency freq;
-  SelOffset offset;
-
-  Serial.print("deleteslot_incdec: item_num="); Serial.print(item_num);
-  Serial.print(", delta="); Serial.println(delta);
-
-  if (delta != 0)
-  {
-    Serial.print("Old item_num="); Serial.println(item_num);
-
-    // bump the slot number, limit to [0, 9]
-    item_num += delta;
-    if (item_num < 0)
-      item_num = 0;
-    else
-      if (item_num > 9)
-        item_num = 9;
-
-    Serial.print("New item_num="); Serial.println(item_num);
-  }
-
-  // draw the row 1 representation of the value
-  Serial.println("Xpoint 1");
-  get_slot(item_num, freq, offset);
-  Serial.println("Xpoint 2");
-  lcd.setCursor(0, 1);
-  lcd.write(BlankRow);
-  if (VfoFrequency == freq)
-  {
-    lcd.setCursor(0, 1);
-    lcd.write("*");
-  }
-  Serial.println("Xpoint 3");
-  lcd.setCursor(4, 1);
-  lcd.write(item_num + '0');
-  lcd.write(":");
-  Serial.println("Xpoint 4");
-  print_freq(freq, -1, 1);
-  Serial.println("Xpoint 5");
-
-  Serial.print("saveslot_incdec: returning item_num="); Serial.println(item_num);
-  return item_num;
-}
-
-//----------------------------------------
-// save the current brightness to EEPROM
-//----------------------------------------
-
-void brightness_action(Menu *menu, int item_num)
-{
-  Serial.println("brightness_action() entered");
-
-  // display an 'action' flash, save brightness to EEPROM
-  menu_flash();
-  save_to_eeprom();
-}
-
-//----------------------------------------
-// adjust the LCD brightness up or down and update menu display
-//----------------------------------------
-
-int brightness_incdec(int item_num, int delta)
-{
-  Serial.print("brightness_incdec: delta="); Serial.println(delta);
+//   menu      address of 'calling' menu
+//   item_num  index of MenuItem we were actioned from
+//----------------------------------------
+
+void deleteslot_action(struct Menu *menu, int item_num)
+{
+  Frequency zero_freq = 0;        // zero value to be saved
+  SelOffset zero_offset = 0;      // zero value to be saved
+  int slot_num = 0;               // the slot we are viewing/restoring
+
+  // get rid of any stray events to this point
+  flush_events();
+
+  // draw row 0 of menu
+  lcd.clear();
+  lcd.write(menu->items[item_num]->title);

-  // convert brighness value to a display value in [1, 16]
-  int index = (LcdBrightness + 1) / 16;
-
-  if (delta != 0)
-  {
-    Serial.print("Old LcdBrightness="); Serial.print(LcdBrightness);
-    Serial.print(", index="); Serial.println(index);
-
-    // first, bump the internal index, limit to range
-    index += delta;
-    if (index < 1)
-      index = 1;
-    else
-      if (index > 16)
-        index = 16;
-
-    Serial.print("New LcdBrightness="); Serial.print(LcdBrightness);
-    Serial.print(", index="); Serial.println(index);
-
-    // put brightness back into global variable and adjust display brightness
-    LcdBrightness = (index * 16) - 1;
-    analogWrite(mc_Brightness, LcdBrightness);
-  }
-
-  // draw the row 1 representation of the value
+  // show row slot info on row 1
+  show_slot_frequency(slot_num);
+
+  // handle events in our own little event loop
+  while (true)
+  {
+    // handle any pending event
+    if (events_pending() > 0)
+    {
+      byte event = pop_event(); // get next event and handle it
+
+      switch (event)
+      {
+        case vfo_RLeft:
+          if (--slot_num < 0)
+            slot_num = 0;
+          break;
+        case vfo_RRight:
+          if (++slot_num >= NumSaveSlots)
+            slot_num = NumSaveSlots - 1;
+          break;
+        case vfo_Click:
+          put_slot(slot_num, zero_freq, zero_offset);
+          menu_flash();
+          break;
+        case vfo_HoldClick:
+          flush_events();
+          return;
+        default:
+          // ignored events we don't handle
+          break;
+      }
+
+      // show row slot info
+      show_slot_frequency(slot_num);
+    }
+  }
+}
+
+//----------------------------------------
+// Draw a bar of a given length on row 1 of LCD.
+//   length  length of the bar [1, 16]
+//----------------------------------------
+
+void draw_row1_bar(int length)
+{
   lcd.setCursor(0, 1);
   lcd.write(BlankRow);
   lcd.setCursor(0, 1);
-  for (int i = 0; i < index; ++i)
-  {
+  for (int i = 0; i < length; ++i)
     lcd.write(ALLSET_CHAR);
-  }
-
-  return item_num;
+}
+
+//----------------------------------------
+// save the current brightness to EEPROM
+//   menu      address of 'calling' menu
+//   item_num  index of MenuItem we were actioned from
+//----------------------------------------
+
+void brightness_action(struct Menu *menu, int item_num)
+{
+  // convert brighness value to a display value in [1, 16]
+  int index = (LcdBrightness + 1) / 16;
+
+  // get rid of any stray events to this point
+  flush_events();
+
+  // draw row 0 of menu, get heading from MenuItem
+  lcd.clear();
+  lcd.write(menu->items[item_num]->title);
+
+  // show row slot info on row 1
+  draw_row1_bar(index);
+
+  // handle events in our own little event loop
+  while (true)
+  {
+    // handle any pending event
+    if (events_pending() > 0)
+    {
+      byte event = pop_event(); // get next event and handle it
+
+      switch (event)
+      {
+        case vfo_RLeft:
+          if (--index < 1)
+            index = 1;
+          break;
+        case vfo_RRight:
+          if (++index > 16)
+            index = 16;
+          break;
+        case vfo_Click:
+          save_to_eeprom();
+          menu_flash();
+          break;
+        case vfo_HoldClick:
+          flush_events();
+          return;
+        default:
+          // ignored events we don't handle
+          break;
+      }
+
+      // adjust display brightness so we can see the results
+      LcdBrightness = (index * 16) - 1;
+      analogWrite(mc_Brightness, LcdBrightness);
+
+      // show brightness value in row 1
+      draw_row1_bar(index);
+    }
+  }
 }

 //----------------------------------------
 // save the current contrast to EEPROM
-//----------------------------------------
-
-void contrast_action(Menu *menu, int item_num)
-{
-  Serial.println("contrast_action() entered");
-
-  // display an 'action' flash, save contrast to EEPROM
-  save_to_eeprom();
-  menu_flash();
-}
-
-//----------------------------------------
-// adjust the LCD contrast up or down and update menu display
-//----------------------------------------
-
-int contrast_incdec(int item_num, int delta)
-{
-  Serial.print("contrast_incdec: delta="); Serial.println(delta);
+//   menu      address of 'calling' menu
+//   item_num  index of MenuItem we were actioned from
+//----------------------------------------
+
+void contrast_action(struct Menu *menu, int item_num)
+{
+  // convert contrast value to a display value in [1, 16]
+  int index = 16 - LcdContrast / 8;
+
+  // get rid of any stray events to this point
+  flush_events();
+
+  // draw row 0 of menu, get heading from MenuItem
+  lcd.clear();
+  lcd.write(menu->items[item_num]->title);

-  // convert brighness value to a display value in [1, 16]
-  int index = 16 - LcdContrast / 8;
-
-  if (delta != 0)
-  {
-    Serial.print("Old LcdContrast="); Serial.print(LcdContrast);
-    Serial.print(", index="); Serial.println(index);
-
-    // first, bump the internal index, limit to range
-    index += delta;
-    if (index < 1)
-      index = 1;
-    else
-      if (index > 16)
-        index = 16;
-
-    Serial.print("New LcdContrast="); Serial.print(LcdContrast);
-    Serial.print(", index="); Serial.println(index);
-
-    // put brightness back into global variable and adjust display brightness
-    LcdContrast = (16 - index) * 8;
-    analogWrite(mc_Contrast, LcdContrast);
-  }
-
-  // draw the row 1 representation of the value
-  lcd.setCursor(0, 1);
-  lcd.write(BlankRow);
-  lcd.setCursor(0, 1);
-  for (int i = 0; i < index; ++i)
-  {
-    lcd.write(ALLSET_CHAR);
-  }
-
-  return item_num;
-}
-
-//----------------------------------------
-// Brightness & Contrast menu with custom menuitems
-//----------------------------------------
-
-struct MenuItem mic_brightness = {NULL, NULL, brightness_action, brightness_incdec};
-struct MenuItem *miac_brightness[] = {&mic_brightness};
-struct Menu brightness_menu = {"Brightness", ARRAY_LEN(miac_brightness), miac_brightness};
-
-struct MenuItem mic_contrast = {NULL, NULL, contrast_action, contrast_incdec};
-struct MenuItem *miac_contrast[] = {&mic_contrast};
-struct Menu contrast_menu = {"Contrast", ARRAY_LEN(miac_contrast), miac_contrast};
+  // show row slot info on row 1
+  draw_row1_bar(index);
+
+  // handle events in our own little event loop
+  while (true)
+  {
+    // handle any pending event
+    if (events_pending() > 0)
+    {
+      byte event = pop_event(); // get next event and handle it
+
+      switch (event)
+      {
+        case vfo_RLeft:
+          if (--index < 1)
+            index = 1;
+          break;
+        case vfo_RRight:
+          if (++index > 16)
+            index = 16;
+          break;
+        case vfo_Click:
+          save_to_eeprom();
+          menu_flash();
+          break;
+        case vfo_HoldClick:
+          flush_events();
+          return;
+        default:
+          // ignored events we don't handle
+          break;
+      }
+
+      // adjust display contrast so we can see the results
+      LcdContrast = (16 - index) * 8;
+      analogWrite(mc_Contrast, LcdContrast);
+
+      // show brightness value in row 1
+      draw_row1_bar(index);
+    }
+  }
+}

 //----------------------------------------
 // Settings menu
 //----------------------------------------

-struct MenuItem mi_brightness = {"Brightness", &brightness_menu, &menu_show, NULL};
-struct MenuItem mi_contrast = {"Contrast", &contrast_menu, &menu_show, NULL};
+struct MenuItem mi_brightness = {"Brightness", NULL, &brightness_action};
+struct MenuItem mi_contrast = {"Contrast", NULL, &contrast_action};
 struct MenuItem *mia_settings[] = {&mi_brightness, &mi_contrast};
 struct Menu settings_menu = {"Settings", ARRAY_LEN(mia_settings), mia_settings};

 //----------------------------------------
-// "save slot" menu
-//----------------------------------------
-
-struct MenuItem mi_saveslot = {"Save slot", NULL, saveslot_action, saveslot_incdec};
-struct MenuItem *mia_saveslot[] = {&mi_saveslot};
-struct Menu saveslot_menu = {"Save slot", ARRAY_LEN(mia_saveslot), mia_saveslot};
-
-//----------------------------------------
-// "restore slot" menu
-//----------------------------------------
-
-struct MenuItem mi_restoreslot = {"Restore slot", NULL, restoreslot_action, restoreslot_incdec};
-struct MenuItem *mia_restoreslot[] = {&mi_restoreslot};
-struct Menu restoreslot_menu = {"Restore slot", ARRAY_LEN(mia_restoreslot), mia_restoreslot};
-
-//----------------------------------------
-// "delete slot" menu
-//----------------------------------------
-
-struct MenuItem mi_deleteslot = {"Delete slot", NULL, deleteslot_action, deleteslot_incdec};
-struct MenuItem *mia_deleteslot[] = {&mi_deleteslot};
-struct Menu deleteslot_menu = {"Delete slot", ARRAY_LEN(mia_deleteslot), mia_deleteslot};
-
-//----------------------------------------
 // main menu
 //----------------------------------------

-struct MenuItem mi_save = {"Save slot", &saveslot_menu, &menu_show, NULL};
-struct MenuItem mi_restore = {"Restore slot", &restoreslot_menu, &menu_show, NULL};
-struct MenuItem mi_del = {"Delete slot", &deleteslot_menu, &menu_show, NULL};
-struct MenuItem mi_settings = {"Settings", &settings_menu, &menu_show, NULL};
+struct MenuItem mi_save = {"Save slot", NULL, &saveslot_action};
+struct MenuItem mi_restore = {"Restore slot", NULL, &restoreslot_action};
+struct MenuItem mi_del = {"Delete slot", NULL, &deleteslot_action};
+struct MenuItem mi_settings = {"Settings", &settings_menu, NULL};
 struct MenuItem *mia_main[] = {&mi_save, &mi_restore, &mi_del, &mi_settings};
 struct Menu menu_main = {"Menu", ARRAY_LEN(mia_main), mia_main};

-
-//----------------------------------------
-// draw the Save, Restore or Delete screen
-//----------------------------------------
-
-void savresdel_show(struct Menu *menu, int slot_num)
-{
-  Frequency freq;
-  SelOffset offset;
-
-  // max length of item strings is "9: xxxxxxxxHz" - 13 chars
-  const int max_len = 13;
-  char buf[MAX_FREQ_CHARS + 1];
-
-  get_slot(slot_num, freq, offset);
-
-  ltochbuff(buf, MAX_FREQ_CHARS, freq);
-  buf[MAX_FREQ_CHARS] = 0;
-
-  // write menu title on first row
-  lcd.clear();
-  lcd.setCursor(0, 0);
-  lcd.write(menu->title);
-
-  // write indexed item on lower row, right-justified
-  lcd.setCursor(0, 1);
-  lcd.write(BlankRow);
-  // show '*' if slot frequency equal to current
-  if (freq == VfoFrequency)
-  {
-    lcd.setCursor(0, 1);
-    lcd.write("*");
-  }
-  lcd.setCursor(NUM_COLS - max_len, 1);
-  lcd.write(slot_num + '0');
-  lcd.write(": ");
-  lcd.write(buf);
-  lcd.write("Hz");
-}
-
-//----------------------------------------
-//----------------------------------------
-
-void save_select(struct Menu *menu, int slot_num)
-{
-  savresdel_show(menu, slot_num);
-
-  while (true)
-  {
-
-  }
-  // display an 'action flash'
-  menu_flash();
-
-  put_slot(slot_num, VfoFrequency, VfoSelectDigit);
-
-  savresdel_show(menu, slot_num);
-}
-
-//----------------------------------------
-//----------------------------------------
-
-void restore_select(struct Menu *menu, int slot_num)
-{
-  // display an 'action flash'
-  menu_flash();
-
-  get_slot(slot_num, VfoFrequency, VfoSelectDigit);
-
-//  savresdel_show(menu, slot_num);  NOT NEEDED?
-}
-
-//----------------------------------------
-//----------------------------------------
-
-void delete_select(struct Menu *menu, int slot_num)
-{
-  // display an 'action flash'
-  menu_flash();
-
-  put_slot(slot_num, 0L, 0);
-
-//  savresdel_show(menu, slot_num);  NOT NEEDED?
-}

 //----------------------------------------
 // Standard Arduino loop() function.
@@ -1592,7 +1420,7 @@
     switch (event)
     {
       case vfo_RLeft:
-        Serial.println("vfo_RLeft");
+        Serial.println("loop: vfo_RLeft");
         VfoFrequency -= offset2bump[VfoSelectDigit];
         if (VfoFrequency < MIN_FREQ)
           VfoFrequency = MIN_FREQ;
@@ -1600,7 +1428,7 @@
           VfoFrequency = MAX_FREQ;
        break;
       case vfo_RRight:
-        Serial.println("vfo_RRight");
+        Serial.println("loop: vfo_RRight");
         VfoFrequency += offset2bump[VfoSelectDigit];
         if (VfoFrequency < MIN_FREQ)
           VfoFrequency = MIN_FREQ;
@@ -1608,32 +1436,28 @@
           VfoFrequency = MAX_FREQ;
         break;
       case vfo_DnRLeft:
-        Serial.println("vfo_DnRLeft");
+        Serial.println("loop: vfo_DnRLeft");
         VfoSelectDigit += 1;
         if (VfoSelectDigit >= MAX_FREQ_CHARS)
           VfoSelectDigit = MAX_FREQ_CHARS - 1;
         break;
       case vfo_DnRRight:
-        Serial.println("vfo_DnRRight");
+        Serial.println("loop: vfo_DnRRight");
         VfoSelectDigit -= 1;
         if (VfoSelectDigit < 0)
           VfoSelectDigit = 0;
         break;
       case vfo_Click:
-        Serial.println("vfo_Click event ignored");
+        Serial.println("loop: vfo_Click event ignored");
         break;
       case vfo_HoldClick:
-        Serial.println("Got vfo_HoldClick: calling menu_show()");
-
-  Serial.print("brightness_menu="); Serial.println((unsigned long) &brightness_menu, HEX);
-  Serial.print("mic_brightness="); Serial.println((unsigned long) &mic_brightness, HEX);
-
-        menu_show(&menu_main, 0);
-        save_to_eeprom();  // save any changes made
+        Serial.println("loop: Got vfo_HoldClick: calling menu_show()");
+        menu_show(&menu_main, 0);    // redisplay the original menu
         show_main_screen();
+        save_to_eeprom();   // save any changes made
         break;
       default:
-        Serial.print("Unrecognized event: "); Serial.println(event);
+        Serial.print("loop: Unrecognized event: "); Serial.println(event);
         break;
     }

@@ -1646,7 +1470,7 @@

       save_to_eeprom();

-      update_dds60(VfoFrequency);
+      dds_update(VfoFrequency);
     }
   }
 }


Reworked comments :)

Reworked comments :)

--- HTTPserver.ino
+++ HTTPserver.ino
@@ -1,10 +1,27 @@
 #include "flashfiles.h"
+
+/***
+ * Brick main web page, builds a page with a section for each enabled module
+ */
+void httpMainWebPage() {
+  String HTMLoutput = readFromFlash("header.html") + readFromFlash("app.html");
+  HTMLoutput.replace("%%TYPE%%",BRICK_TYPE);        // Replace brick type in template
+
+#if defined(MODULE_DHT22)
+  HTMLoutput = dht22MainWebPage(HTMLoutput);        // DHT22 module main app section
+#endif
+#if defined(MODULE_STRIP)
+  HTMLoutput = stripMainWebPage(HTMLoutput);        // Strip module main app section
+#endif
+
+  server.send(200, "text/html", HTMLoutput);
+}

 /***
  * Serves a file directly from Flash memory
  * Files are defined in websites.h, generated using convertWebFiles.sh
  *
- * CAUTION : Ressources have to be gziped (*.ico, *.js, *.css, etc...)
+ * CAUTION : Some ressources have to be gziped (*.ico, *.js, *.css, *.png, etc...)
  */
 bool serveFromFlash(String path) {
   if(path.endsWith("/")) path += "index.html";
@@ -30,7 +47,7 @@
       long tBefore = millis();
       client.write(*filecontent, SERVE_FROM_FLASH_PACKET_SIZE);

-      //Logln("[NFO] Served " + String(files[i].filename) + " from Flash in " + String(millis()-tBefore) + "ms");
+      Logln("[NFO] Served " + String(files[i].filename) + " from Flash in " + String(millis()-tBefore) + "ms");
       return true;
     }
   }
@@ -38,7 +55,7 @@
 }

 /***
- * Reads a file directly from Flash memory
+ * Reads a file directly from Flash memory to a String
  */
 String readFromFlash(String path) {
   if(path.endsWith("/")) path += "index.html";
@@ -63,7 +80,10 @@
   return String("ERROR");
 }

-
+/***
+ * Handle all undefined endpoints, even resource files directly stored on flash
+ * 404 page filled with system informations
+ */
 void handleNotFound() {

   // try to find the file in the flash
@@ -90,17 +110,3 @@
   server.send(404, "text/plain", message);
 }

-void httpMainWebPage() {
-  String HTMLoutput = readFromFlash("header.html") + readFromFlash("app.html");
-  HTMLoutput.replace("%%TYPE%%",BRICK_TYPE);    // Replace brick type in template
-
-#if defined(MODULE_DHT22)
-  HTMLoutput = dht22MainWebPage(HTMLoutput);        // DHT22 module main app section
-#endif
-#if defined(MODULE_STRIP)
-  HTMLoutput = stripMainWebPage(HTMLoutput);        // DHT22 module main app section
-#endif
-
-  server.send(200, "text/html", HTMLoutput);
-}
-


Switch to an 8 element ringg buffer for the 433 pulses to prevent overruns while processing

-- Reorganizes some of the verbose logging
-- Re-init RF69 after reset()
-- Will now lower OOK threshold if there's <5 errors per period

--- arduino/Powermon433/Powermon433.ino
+++ arduino/Powermon433/Powermon433.ino
@@ -56,6 +56,13 @@
   uint8_t data[4];
 } decoder;

+static volatile struct tagPulseBuffer
+{
+  uint8_t head; // where new elements are pushed
+  uint8_t tail; // where elements are popped
+  uint16_t pulse[8];
+} pulsebuff;
+
 #if defined(DPIN_OOK_RX)
 static int8_t g_RxTemperature;
 static uint8_t g_RxFlags;
@@ -78,7 +85,35 @@
 #define VECT PCINT2_vect
 #endif

-volatile uint16_t pulse_433;
+static uint8_t ringbuffSize(void)
+{
+  return sizeof(pulsebuff.pulse)/sizeof(*pulsebuff.pulse);
+}
+
+static void ringbuffPush(uint16_t v)
+{
+  // Not thread-safe, only call from ISR
+  uint8_t newIdx = (pulsebuff.head + 1) % ringbuffSize();
+  if (newIdx != pulsebuff.tail)
+  {
+    pulsebuff.pulse[pulsebuff.head] = v;
+    pulsebuff.head = newIdx;
+  }
+}
+
+static uint16_t ringbuffPop(void)
+{
+  // Threadsafe
+  ATOMIC_BLOCK(ATOMIC_FORCEON)
+  {
+    uint8_t idx = pulsebuff.tail;
+    if (pulsebuff.head == idx)
+      return 0;
+    uint16_t retVal = pulsebuff.pulse[idx];
+    pulsebuff.tail = (idx + 1) % ringbuffSize();
+    return retVal;
+  }
+}

 static void pinChange(void)
 {
@@ -86,8 +121,7 @@

   uint16_t now = micros();
   uint16_t cnt = now - last_433;
-  if (cnt > 10)
-    pulse_433 = cnt;
+  ringbuffPush(cnt);

   last_433 = now;
 }
@@ -241,6 +275,16 @@
 }
 #endif // defined(DPIN_OOK_TX)

+static void setRF69FreqL(uint32_t khz)
+{
+  uint32_t val = khz * (524288.0 / 32000.0);
+  rf69ook_writeReg(0x01, 0x04); // standby
+  rf69ook_writeReg(0x07, (val >> 16) & 0xff);
+  rf69ook_writeReg(0x08, (val >> 8) & 0xff);
+  rf69ook_writeReg(0x09, val & 0xff);
+  rf69ook_writeReg(0x01, 0x10); // RX
+}
+
 static void setRF69Freq(char *buf)
 {
   static uint32_t khz;
@@ -252,24 +296,21 @@
     khz = atol(buf);

   Serial.print(khz, DEC); Serial.println(F("kHz"));
-
-  uint32_t val = khz * (524288.0 / 32000.0);
-  rf69ook_writeReg(0x01, 0x04); // standby
-  rf69ook_writeReg(0x07, (val >> 16) & 0xff);
-  rf69ook_writeReg(0x08, (val >> 8) & 0xff);
-  rf69ook_writeReg(0x09, val & 0xff);
-  rf69ook_writeReg(0x01, 0x10); // RX
+  setRF69FreqL(khz);
 }

 static void setRf69Thresh(uint8_t val)
 {
-#if defined(DUMP_RX)
-  Serial.print(F("Errcount: ")); Serial.print(g_RxErrCnt, DEC);
-  Serial.print(F(" OokFixedThresh="));
-  Serial.println(val, DEC);
-#endif
-  rf69ook_writeReg(0x1d, val);
-  g_RxOokFloor = val;
+  if (g_RxOokFloorVerbose)
+  {
+    Serial.print("E="); Serial.print(g_RxErrCnt, DEC);
+    Serial.print(" T="); Serial.println(val, DEC);
+  }
+  if (g_RxOokFloor != val)
+  {
+    rf69ook_writeReg(0x1d, val);
+    g_RxOokFloor = val;
+  }
 }

 static void resetRf69(void)
@@ -281,6 +322,7 @@
   digitalWrite(DPIN_RF69_RESET, LOW);
   pinMode(DPIN_RF69_RESET, INPUT);
   delay(5);
+  rf69ook_init();
   Serial.println(F("RFM reset"));
 #endif // DPIN_RF69_RESET
 }
@@ -485,7 +527,7 @@
   Serial.print(F(" dBm, Floor: ")); Serial.print(g_RxOokFloor, DEC);
 }

-static void decodeRxPacket(void)
+static void dumpRxData(void)
 {
 #if defined(DUMP_RX)
   for (uint8_t i=0; i<decoder.pos; ++i)
@@ -496,6 +538,11 @@
   }
   Serial.println();
 #endif
+}
+
+static void decodeRxPacket(void)
+{
+  dumpRxData();

   uint16_t val16 = *(uint16_t *)decoder.data;
   if (crc8(decoder.data, 3) == 0)
@@ -591,13 +638,8 @@
 static void ookRx(void)
 {
 #if defined(DPIN_OOK_RX)
-  uint16_t v;
-  ATOMIC_BLOCK(ATOMIC_FORCEON)
-  {
-    v = pulse_433;
-    pulse_433 = 0;
-  }
-  if (v != 0)
+  uint16_t v = ringbuffPop();
+  while (v != 0)
   {
     if (decodeRxPulse(v) == 1)
     {
@@ -607,10 +649,11 @@
       decodeRxPacket();
       resetDecoder();
     }
+    v = ringbuffPop();
   }

   // If it has been more than 250ms since the last receive, dump the data
-  else if (g_RxDirty && (millis() - g_RxLast) > 250U)
+  if (g_RxDirty && (millis() - g_RxLast) > 250U)
   {
  #if defined(DUMP_RX)
    Serial.print('['); Serial.print(millis(), DEC); Serial.print(F("] "));
@@ -618,7 +661,7 @@
     Serial.print(F("Energy: ")); Serial.print(g_RxWattHours, DEC);
     Serial.print(F(" Wh, Power: ")); Serial.print(g_RxWatts, DEC);
     Serial.print(F(" W, Temp: ")); Serial.print(g_RxTemperature, DEC);
-    Serial.print(F(" F, "));
+    Serial.print(F(" F,"));
     printRssi();
     Serial.print(F(", LowBat: ")); Serial.println(g_RxFlags >> 7, DEC);

@@ -644,7 +687,7 @@
       offset = 2;
     else if (g_RxErrCnt > 250)
       offset = 1;
-    else if (g_RxErrCnt < 1)
+    else if (g_RxErrCnt < 5)
       offset = -1;

     if (offset != 0)
@@ -652,11 +695,6 @@

     g_RxErrStart = millis();
     g_RxErrCnt = 0;
-
-    if (g_RxOokFloorVerbose)
-    {
-      Serial.print("RxOokFloor="); Serial.println(g_RxOokFloor, DEC);
-    }
   }
 #endif
 #endif // DPIN_OOK_RX


Ongoing updates to fix frequency issues

Ongoing updates to fix frequency issues

--- balloon_proto_2/balloon_proto_2.ino
+++ balloon_proto_2/balloon_proto_2.ino
@@ -8,22 +8,27 @@
 #include <TinyGPS.h>
 #include <SoftwareSerial.h>
 #include <Wire.h>
-#include "LowPower.h"

 #define WSPR_TONE_SPACING       146           // ~1.46 Hz
 #define WSPR_CTC                10672         // CTC value for WSPR
-#define WSPR_DEFAULT_FREQ       14150000UL    // 10140200UL
+#define WSPR_DEFAULT_FREQ       10140200UL    //1415000000ULL    // 10140200UL
+
+int lcdPin = 12;

 Si5351 si5351;
 JTEncode jtencode;
-TinyGPS gps;
-SoftwareSerial ss(4, 2);
+TinyGPS gps_data;
+SoftwareSerial gps(4, 2);
+unsigned long fix_age;

-unsigned long freq;
-char message[] = "KD8UPW EM79";
+SoftwareSerial lcd(255, lcdPin);
+
+uint64_t freq;
+
+char message[] = "NOCALL AA00";
 char call[] = "KD8UPW";
-char loc[] = "EM79";
+char loc[] = "AA00";
 uint8_t dbm = 27;
 uint8_t tx_buffer[255];
 uint8_t symbol_count;
@@ -31,7 +36,6 @@

 // Global variables used in ISRs
 volatile bool proceed = false;
-volatile bool processing = false;

 // Timer interrupt vector.  This toggles the variable we use to gate
 // each column of output to ensure accurate timing.  Called whenever
@@ -42,7 +46,8 @@
 }

 void setup() {
-  ss.begin(9600);
+  init_lcd();
+  gps.begin(9600);

   freq = WSPR_DEFAULT_FREQ;
   ctc = WSPR_CTC;
@@ -73,6 +78,15 @@
   interrupts();            // Re-enable interrupts.
 }

+void init_lcd() {
+  pinMode(lcdPin, OUTPUT);
+  digitalWrite(lcdPin, HIGH);
+  lcd.begin(9600);
+  delay(100);
+  lcd.write(12);
+  lcd.write(17);
+}
+
 void loop() {
   if(can_transmit()) {
     encode();
@@ -82,23 +96,23 @@

 bool can_transmit() {
   float lat, lon;
-  unsigned long fix_age;
   int year, retries;
   byte month, day, hour, minute, second, hundredths;

   populate_gps_data();
   while (retries++ < 10) {
-    gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &fix_age);
+    gps_data.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &fix_age);
     if (fix_age != TinyGPS::GPS_INVALID_AGE) {
       break;
     }
+    lcd.print("Bad GPS Data"); lcd.write(13);
     delay(1000);
     populate_gps_data();
   }
   if (retries >= 10) {
     return false;
   }
-  gps.f_get_position(&lat, &lon, &fix_age);
+  gps_data.f_get_position(&lat, &lon, &fix_age);
   if (!valid_coords(lat, lon)) {
     return false;
   }
@@ -106,13 +120,14 @@
     delay((60 - second) * 1000);
   }
   to_maidenhead(lat, lon);
+  display_gps_data(lat, lon);
   return true;
 }

 void populate_gps_data() {
   while (true) {
-    while (ss.available()) {
-      if (gps.encode(ss.read())) {
+    while (gps.available()) {
+      if (gps_data.encode(gps.read())) {
         return;
       }
     }
@@ -137,6 +152,20 @@
   loc[5] = '\0';
 }

+void display_gps_data(double lat, double lon) {
+  lcd.write(12);
+  lcd.print("Lat:"); lcd.print((int)floor(lat)); lcd.print(" Lon:"); lcd.print((int)floor(lon)); lcd.write(13);
+  lcd.print("MDNHD: "); lcd.print(loc);
+  delay(50);
+}
+
+void display_transmitting() {
+  lcd.write(12);
+  lcd.print("XMIT ... "); lcd.write(13);
+  lcd.print(call); lcd.print(" "); lcd.print(loc);
+  delay(50);
+}
+
 // Loop through the string, transmitting one character at a time.
 void encode()
 {
@@ -150,18 +179,17 @@

   // Reset the tone to the base frequency and turn on the output
   si5351.output_enable(SI5351_CLK0, 1);
-//  digitalWrite(LED_PIN, HIGH);

   for(i = 0; i < symbol_count; i++)
   {
-      si5351.set_freq((freq * 100) + (tx_buffer[i] * tone_spacing), SI5351_CLK0);
+      si5351.set_freq((freq * SI5351_FREQ_MULT) + (tx_buffer[i] * tone_spacing), SI5351_CLK0);
       proceed = false;
       while(!proceed);
   }

   // Turn off the output
   si5351.output_enable(SI5351_CLK0, 0);
-  //digitalWrite(LED_PIN, LOW);
+
 }


waffle  basic operation (6.3.2) bug fixed

--- arduino/opencr_arduino/opencr/libraries/turtlebot3/examples/turtlebot3_waffle/turtlebot3_core/turtlebot3_core.ino
+++ arduino/opencr_arduino/opencr/libraries/turtlebot3/examples/turtlebot3_waffle/turtlebot3_core/turtlebot3_core.ino
@@ -569,6 +569,7 @@
     saved_tick[RIGHT] = current_tick[RIGHT];

     diff_encoder = TEST_DISTANCE / (0.207 / 4096); // (Circumference of Wheel) / (The number of tick per revolution)
+    tTime[6] = millis();
   }
   else if (buttons & (1<<1))
   {
@@ -576,6 +577,7 @@
     saved_tick[RIGHT] = current_tick[RIGHT];

     diff_encoder = (TEST_RADIAN * TURNING_RADIUS) / (0.207 / 4096);
+    tTime[6] = millis();
   }

   if (move[LINEAR])
@@ -583,6 +585,7 @@
     if (abs(saved_tick[RIGHT] - current_tick[RIGHT]) <= diff_encoder)
     {
       goal_velocity_from_button[LINEAR]  = 0.05;
+      tTime[6] = millis();
     }
     else
     {
@@ -595,6 +598,7 @@
     if (abs(saved_tick[RIGHT] - current_tick[RIGHT]) <= diff_encoder)
     {
       goal_velocity_from_button[ANGULAR]= -0.7;
+      tTime[6] = millis();
     }
     else
     {


Typo fix

Typo fix

Typo fix

--- DataLogger/DataLogger.ino
+++ DataLogger/DataLogger.ino
@@ -49,7 +49,7 @@
 //Set pins for MISO/MOSI/SS/PP
 const int lcdSS = 2; //SS for LCD
 const int sdSS = 10; //SS for sd card logger was already defined, but
-//pin 10 (the hardware SS pin) must be set to output or the SD library
+//pin 10 (the hardware SS pin) must be set to output or the SdFat library
 //won't work
 const int MOSIpin = 11; //MOSI pin
 const int MISOpin = 12; //MISO pin


Fix copy/paste error

Fix copy/paste error

--- SonoffBoilerplate.ino
+++ SonoffBoilerplate.ino
@@ -529,7 +529,7 @@

   //setup input
   pinMode(SONOFF_INPUT, INPUT);
-  attachInterrupt(SONOFF_BUTTON, toggleInputState, CHANGE);
+  attachInterrupt(SONOFF_INPUT, toggleInputState, CHANGE);

   //setup relay
   //TODO multiple relays
@@ -599,7 +599,7 @@
   switch (cmd) {
     case CMD_WAIT:
       break;
-    case CMD_BUTTON_CHANGE:
+    case CMD_BUTTON_CHANGE: {
       int currentState = digitalRead(SONOFF_BUTTON);
       if (currentState != buttonState) {
         if (buttonState == LOW && currentState == HIGH) {
@@ -618,7 +618,7 @@
           startPress = millis();
         }
         buttonState = currentState;
-      }
+      }}
       break;

   }


startup serial updated. mqtt still disabled

--- Exhibit_MomentumTable.ino
+++ Exhibit_MomentumTable.ino
@@ -61,7 +61,6 @@
 client.setServer(mqtt_server, 1883);
 client.setCallback(callback);
 Serial.begin(115200);
-Serial.println("");
 /////////////////////////////
 delay(5000);
 motionControlStart(); // remove when MQTT is active. testing only


Fixed an embarassing bug.

Fixed an embarassing bug.

git-svn-id: d8bfcd070c2c81762cca1b3912331324182919ba@14806 0d6f1817-ed0e-0410-87c9-987e46238f29

--- zimodem/zcommand.ino
+++ zimodem/zcommand.ino
@@ -1129,6 +1129,12 @@

 void ZCommand::reSendLastPacket(WiFiClientNode *conn)
 {
+  if(conn == NULL)
+  {
+    Serial.print("[ 0 0 0 ]");
+    Serial.print(EOLN);
+  }
+  else
   if(conn->lastPacketLen == 0) // never used, or empty
   {
     Serial.printf("[ %d %d %d ]",conn->id,conn->lastPacketLen,0);
@@ -1152,7 +1158,7 @@
     currentExpiresTimeMs = millis() + 1000;
   if(!crReceived)
     return;
-  delay(200); // give a pause after receiving command before responding
+  //delay(200); // give a pause after receiving command before responding
   // the delay doesn't affect xon/xoff because its the periodic transmitter that manages that.
   doSerialCommand();
 }
@@ -1245,7 +1251,7 @@
   {
     XON=false;
     firstConn = conns;
-    while(firstConn->isConnected())
+    while(firstConn != NULL)
     {
       firstConn->lastPacketLen = 0;
       firstConn = firstConn->next;


added a Fluxamasynth, moved some of the pins around

--- examples/UNTZtrument_Step_Seq/UNTZtrument_Step_Seq.ino
+++ examples/UNTZtrument_Step_Seq/UNTZtrument_Step_Seq.ino
@@ -24,16 +24,20 @@
 // still have trouble with notes all off when switch layers and grid sets
 // need to check if long notes still work when changing button grid marks or layer and other switches
 // need a scale with just the mt32 drumkit notes
-// volumes left are right controll (fade)
 // flash notes on other layers as they are played so we can see where the notes are being played on other layers
 // add load/save state by midi note export and recording on an external device
 // need to switch to new instrument on grid switch
 // maybe hide play bar when scrolling to avoid confusion
+// add an SD card reader to load and save multiple sets and larger sets and remove some of the restrictions that we have for the EEPROM

 #include <Wire.h>
 #include <EEPROM.h>
 #include <Adafruit_Trellis.h>
 #include <Adafruit_UNTZtrument.h>
+#include <Fluxamasynth.h>
+#include <PgmChange.h>
+
+Fluxamasynth synth;

 #ifndef HELLA
 // A standard UNTZtrument has four Trellises in a 2x2 arrangement
@@ -58,12 +62,12 @@

 // Encoder on pins 4,5 sets tempo.  Optional, not present in
 // standard UNTZtrument, but won't affect things if unconnected.
-enc eScaleOffset(5, 4);
+enc eScaleOffset(5, A4);
 enc eDisplayOffset(9, 8);
 enc eTempo(7, 6);
 enc eVolume(11, 10);

-#define BUTTON_WIDTH            13
+#define BUTTON_WIDTH            A5
 #define BUTTON_GRID             0
 #define BUTTON_PROGRAM_CHANGE   1
 #define BUTTON_LAYER            12
@@ -425,6 +429,7 @@
           {
             uint8_t temp = channels[layer];
             usbMIDI.sendNoteOff(pgm_read_byte(&scales[scale_notes[layer]][6-x + y*7] ) , 127, temp);
+            synth.noteOff(pgm_read_byte(&scales[scale_notes[layer]][6-x + y*7] ) , 127);
             untztrument.clrLED(i);

             refresh = true;
@@ -468,6 +473,7 @@
                 {
                   uint8_t temp2 = channels[layer];
                   usbMIDI.sendNoteOff(pgm_read_byte(&scales[scale_notes[layer]][y + noteOffset[layer][playing_grid_set]] ) , 127, temp2);
+                  synth.noteOff(temp2, pgm_read_byte(&scales[scale_notes[layer]][y + noteOffset[layer][playing_grid_set]] ));
                 }
               }
               else // Turn on
@@ -482,6 +488,7 @@
               {
                 uint8_t temp = channels[layer];
                 usbMIDI.sendNoteOn(pgm_read_byte(&scales[scale_notes[layer]][6-x + y*7] ) , 127, temp);
+                synth.noteOn(temp, pgm_read_byte(&scales[scale_notes[layer]][6-x + y*7] ) , 127);
                 untztrument.setLED(i);
               }
               else
@@ -510,6 +517,8 @@
               instrument[layer] = temp;

               usbMIDI.sendProgramChange(temp, channels[layer]);
+              synth.programChange(0, channels[layer], temp);
+
               force_first_note = true;

               // Turn on column and row for a beat to indicate selection
@@ -537,6 +546,7 @@
               instrument[layer] = temp;

               usbMIDI.sendProgramChange(temp, channels[layer]);
+              synth.programChange(0, channels[layer], temp);
               force_first_note = true;

               // Turn on column and row for a beat to indicate selection
@@ -777,6 +787,8 @@
         {
           uint8_t temp = channels[layer_index];
           usbMIDI.sendNoteOff(pgm_read_byte(&scales[scale_notes[layer_index]][row + noteOffset[layer_index][playing_grid_set]] ) , 127, temp);
+          synth.noteOff(temp, pgm_read_byte(&scales[scale_notes[layer_index]][row + noteOffset[layer_index][playing_grid_set]] ));
+
         }
       }
     }
@@ -801,6 +813,7 @@
       volume[layer] = temp;
       // send change volume on channels
       usbMIDI.sendControlChange(7, temp, channels[layer]);
+      //synth.controlChange(0, 7, temp, channels[layer]);
     }

     // Turn on new column
@@ -815,6 +828,7 @@
         {
           uint8_t temp = channels[layer_index];
           usbMIDI.sendNoteOn(pgm_read_byte(&scales[scale_notes[layer_index]][row + noteOffset[layer_index][playing_grid_set]]), 127, temp);
+          synth.noteOn(temp, pgm_read_byte(&scales[scale_notes[layer_index]][row + noteOffset[layer_index][playing_grid_set]]), 127);
           force_first_note = false; // clear trigger if it was set
         }
       }


Add on-screen message

Add on-screen message

--- sketch.ino
+++ sketch.ino
@@ -8,9 +8,14 @@
   GD.begin();
   GD.cmd_memset(0, 0, 480UL * 272UL);   // clear the bitmap
   GD.Clear();                           // draw the bitmap
+
+  GD.ColorRGB(0x101020);
+  GD.cmd_text(240, 136, 31, OPT_CENTER, "sketch demo");
+
   GD.BitmapLayout(L8, 480, 272);
   GD.BitmapSize(NEAREST, BORDER, BORDER, 480, 272);
   GD.Begin(BITMAPS);
+  GD.ColorRGB(0xffffff);
   GD.Vertex2ii(0, 0);
   GD.swap();
   GD.cmd_sketch(0, 0, 480, 272, 0, L8); // start sketching


diketuk pintu seq

diketuk pintu seq

--- PintuKetok/PintuKetok.ino
+++ PintuKetok/PintuKetok.ino
@@ -24,7 +24,7 @@
 unsigned long smallgap;
 unsigned long thisgap;
 int seq_pos, seq_sub;
-
+unsigned long tolerance;
 unsigned long selisih(unsigned long a, unsigned long b)
 {
 	//--selisih untuk unsigned
@@ -36,7 +36,7 @@

 void reset_seq()
 {
-	seq_sub = 0; seq_pos = 0;
+	seq_sub = 1; seq_pos = 0;
 }

 void setup() {
@@ -44,22 +44,32 @@
 	pinMode(PIN_INPUT, INPUT);
 	digitalWrite(PIN_INPUT, PIN_DEFAULT);
 	seq_pos = 0;
-	seq_sub = 0;
+	seq_sub = 1;
+	smallgap = 400;
+	tolerance = TOLERANCE;
 }

 void loop ()
 {
-	while (digitalRead(PIN_INPUT)==PIN_DEFAULT);
 	lasthit = millis();
-	while (digitalRead(PIN_INPUT)==PIN_ON);
+	while (digitalRead(PIN_INPUT)==PIN_DEFAULT)
+		while (digitalRead(PIN_INPUT)==PIN_DEFAULT)
+			delay(50);
 	thisgap = millis() - lasthit;
+	while (digitalRead(PIN_INPUT)==PIN_ON)
+		while (digitalRead(PIN_INPUT)==PIN_ON)
+			delay(50);

-	if (seq_pos==0 && seq_sub==0)
+	if (seq_pos==0 && seq_sub<=1)
+	{
 		smallgap = thisgap;
+		tolerance = smallgap/2;
+	}
 	Serial.print(thisgap);
 	Serial.print(" ");
-	Serial.println(smallgap);
-	if (selisih(thisgap, smallgap)<TOLERANCE)
+	Serial.print(smallgap);
+	Serial.print(" ");
+	if (selisih(thisgap, smallgap)<tolerance)
 	{
 		//-- small gap, expecting seq_sub complete
 		if (seq_sub<seq[seq_pos])
@@ -72,16 +82,18 @@
 			reset_seq();
 		}
 	}
-	else
+	else if (thisgap > smallgap)
 	{
 		//-- big gap, expecting seq_pos advance
-		if (seq_sub==seq[seq_pos])
+		if (seq_sub>=seq[seq_pos])
 		{
-			seq_sub = 0;
+			seq_sub = 1;
 			seq_pos = seq_pos+1;
 			if (seq_pos>=(SEQ_LENGTH-1))
 			{
 				//-- finish
+				Serial.println("sequence bener!");
+				reset_seq();
 			}
 		}
 		else
@@ -89,6 +101,7 @@
 			reset_seq();
 		}
 	}
+	else {reset_seq();}
 	Serial.print(seq_pos);
 	Serial.print(" ");
 	Serial.print(seq_sub);


Changed how debugging messages toggle

Changed how debugging messages toggle

minor change

--- embedded/Crossfire_Program/Crossfire_Program.ino
+++ embedded/Crossfire_Program/Crossfire_Program.ino
@@ -54,11 +54,11 @@

 // Parameters
 /*******************************************************************************************/
-#define DEBUG //Defining DEBUG turns ON debugging messages
+#define DEBUG 1 //Defining DEBUG turns ON debugging messages

 #define commsTimeout 200 //The maximum time that a received serial command can take, in mS

-#define ballReleaseTime 100 //The time that the solenoid needs to be activated for to release a ball, in mS
+#define ballReleaseTime 20 //The time that the solenoid needs to be activated for to release a ball, in mS

 #define angleLowest 30 //The minimum allowable angle
 #define angleHighest 150 //The maximum allowable angle
@@ -139,7 +139,7 @@
   /*******************************************************************************************/
   Serial.begin(9600);
   Serial.setTimeout(commsTimeout);
-#ifdef DEBUG
+#if DEBUG==1
   Serial.println("Arduino Start");
 #endif

@@ -206,7 +206,7 @@
         Serial.read(); //Remove the 'O' from the serial buffer.
         //Initialization Sequence detected!

-#ifdef DEBUG
+#if DEBUG==1
         Serial.println("'G O' found!");
 #endif

@@ -248,7 +248,7 @@
     //Change servo angle offset
     offset[buffer[0]]=(char) buffer[1]; //Changed to a signed byte
   default:
-#ifdef DEBUG
+#if DEBUG==1
     Serial.print("Unrecognized command ID: ");
     Serial.println(commandID);
 #endif
@@ -266,7 +266,7 @@

   //  unsigned int output =   (((unsigned int) angle-1)*137)/29+900; // 137/29 = 4.724 = 1200/254, the scaling factor to get to uS

-#ifdef DEBUG
+#if DEBUG==1
   Serial.print("Setting shooter ");
   Serial.print(shooterNum);
   Serial.print(" to ");
@@ -293,7 +293,7 @@
       servo1.write(angle);
       break;
     default:
-#ifdef DEBUG
+#if DEBUG==1
       Serial.print("Unrecognized shooter Num: ");
       Serial.println(shooterNum);
 #endif
@@ -309,12 +309,12 @@
 //This function releases one BB (hopefully) from shooter <shooterNum>
 void releaseBall(byte shooterNum) {

-#ifdef DEBUG
+#if DEBUG==1
   Serial.print("Releasing ball from shooter: ");
   Serial.println(shooterNum);
 #endif
   if (shooterNum<1 || shooterNum>3) { //Check that the shooter number is valid
-#ifdef DEBUG
+#if DEBUG==1
     Serial.print("Unrecognized shooter Num: ");
     Serial.println(shooterNum);
 #endif
@@ -339,7 +339,7 @@
       if (millis()>ballReleaseTimer[i]){ //If enough time has passed
         digitalWrite(solenoidPins[i],LOW); //Deactivate the solenoid: close the passage
         ballReleasing[i]=0; //Indicate that the ball is no longer being released
-#ifdef DEBUG
+#if DEBUG==1
         Serial.print("Deactivating solenoid: ");
         Serial.println(i);
 #endif


Extreme PID values chilled

Extreme PID values chilled

I wish

--- Firmware/R2-Quadcopter/PID.ino
+++ Firmware/R2-Quadcopter/PID.ino
@@ -3,18 +3,34 @@
   // Executer le PID et en tirer le resultat
   if (!auto_stabilisation_mode) {
     pid_roll_out = ROLL_PID_KP * roll_error + ROLL_PID_KI * Integral_roll_error * dt + ROLL_PID_KD * Derivative_roll_error / dt;
+    if(pid_roll_out > ROLL_PID_MAX)pid_roll_out = ROLL_PID_MAX;
+    else if(pid_roll_out < ROLL_PID_MIN)pid_roll_out = ROLL_PID_MIN;
+
     pid_pitch_out = PITCH_PID_KP * pitch_error + PITCH_PID_KI * Integral_pitch_error * dt + PITCH_PID_KD * Derivative_pitch_error / dt;
+    if(pid_pitch_out > PITCH_PID_MAX)pid_pitch_out = PITCH_PID_MAX;
+    else if(pid_pitch_out < PITCH_PID_MIN)pid_pitch_out = PITCH_PID_MIN;
+
     pid_yaw_out = YAW_PID_KP * yaw_error + YAW_PID_KI * Integral_yaw_error * dt + YAW_PID_KD * Derivative_yaw_error / dt;
-
+    if(pid_yaw_out > YAW_PID_MAX)pid_yaw_out = YAW_PID_MAX;
+    else if(pid_yaw_out < YAW_PID_MIN)pid_yaw_out = YAW_PID_MIN;
+
     pid_setpoint_update();
     pid_errors_update();
     pid_calculate_Int_and_Der();
   }
   else if (auto_stabilisation_mode) {
     pid_roll_out = ROLL_PID_KP * AS_roll_error + ROLL_PID_KI * AS_Integral_roll_error * dt + ROLL_PID_KD * AS_Derivative_roll_error / dt;
+    if(pid_roll_out > ROLL_PID_MAX)pid_roll_out = ROLL_PID_MAX;
+    else if(pid_roll_out < ROLL_PID_MIN)pid_roll_out = ROLL_PID_MIN;
+
     pid_pitch_out = PITCH_PID_KP * AS_pitch_error + PITCH_PID_KI * AS_Integral_pitch_error * dt + PITCH_PID_KD * AS_Derivative_pitch_error / dt;
+    if(pid_pitch_out > PITCH_PID_MAX)pid_pitch_out = PITCH_PID_MAX;
+    else if(pid_pitch_out < PITCH_PID_MIN)pid_pitch_out = PITCH_PID_MIN;
+
     pid_yaw_out = YAW_PID_KP * yaw_error + YAW_PID_KI * Integral_yaw_error * dt + YAW_PID_KD * Derivative_yaw_error / dt;//On laisse le yaw comme avant car il ne doit pas etre affecté pas l'auto_dajust
-
+    if(pid_yaw_out > YAW_PID_MAX)pid_yaw_out = YAW_PID_MAX;
+    else if(pid_yaw_out < YAW_PID_MIN)pid_yaw_out = YAW_PID_MIN;
+
     pid_setpoint_update();
     AS_errors_update();
     pid_calculate_AS_Int_and_Der();


Call write() not rawWrite()

Call write() not rawWrite()

rawWrite() was renamed write() in 29776161178517a81da1b52ea0cc85d2193030f0

--- examples/SoftWire_MLX90614/SoftWire_MLX90614.ino
+++ examples/SoftWire_MLX90614/SoftWire_MLX90614.ino
@@ -69,7 +69,7 @@
   digitalWrite(LED_BUILTIN, HIGH); delayMicroseconds(50);
   // Send command
   errors += i2c.startWait(address, SoftWire::writeMode);
-  errors += i2c.rawWrite(command);
+  errors += i2c.write(command);

   // Read results
   errors += i2c.repeatedStart(address, SoftWire::readMode);


Changed example

Changed example

--- examples/eepromExample/eepromExample.ino
+++ examples/eepromExample/eepromExample.ino
@@ -15,7 +15,7 @@
 // you always needs this include.
 #include <EepromAbstraction.h>

-const unsigned int romStart = 800;
+const unsigned int romStart = 2000;

 // if you are using the I2c based eeprom you need the line below
 #include <EepromAbstractionWire.h>
@@ -28,8 +28,7 @@
 // comment / uncomment to select
 //AvrEeprom anEeprom;

-// When you want to use an i2c unit use the code below, for I2C roms you also need the AT24CX library which
-// is available here: https://github.com/cyberp/AT24Cx
+// When you wish to use AT24 based i2c EEPROMs (Uses Wire library)
 // comment / uncomment to select
 I2cAt24Eeprom anEeprom(0x50, PAGESIZE_AT24C128);

@@ -39,8 +38,8 @@
 	Serial.begin(9600);
 	while(!Serial);

-  // if you are using the i2c eeprom, you must include this line below, not needed otherwise.
-  Wire.begin();
+	// if you are using the i2c eeprom, you must include this line below, not needed otherwise.
+	Wire.begin();

 	Serial.println("Eeprom example starting");


Delete mlxtest.ino

Delete mlxtest.ino

--- AnetA8alert_MLX90614-MQ2-Library/AnetA8alert_MLX90614-MQ2-Library/examples/mlxtest/mlxtest.ino
+++ AnetA8alert_MLX90614-MQ2-Library/AnetA8alert_MLX90614-MQ2-Library/examples/mlxtest/mlxtest.ino
@@ -1,40 +0,0 @@
-/***************************************************
-  This is a library example for the MLX90614 Temp Sensor
-
-  Designed specifically to work with the MLX90614 sensors in the
-  adafruit shop
-  ----> https://www.adafruit.com/products/1748
-  ----> https://www.adafruit.com/products/1749
-
-  These sensors use I2C to communicate, 2 pins are required to
-  interface
-  Adafruit invests time and resources providing this open source code,
-  please support Adafruit and open-source hardware by purchasing
-  products from Adafruit!
-
-  Written by Limor Fried/Ladyada for Adafruit Industries.
-  BSD license, all text above must be included in any redistribution
- ****************************************************/
-
-#include <Wire.h>
-#include <MLX90614.h>
-
-Adafruit_MLX90614 mlx = Adafruit_MLX90614();
-
-void setup() {
-  Serial.begin(9600);
-
-  Serial.println("Adafruit MLX90614 test");
-
-  mlx.begin();
-}
-
-void loop() {
-  Serial.print("Ambient = "); Serial.print(mlx.readAmbientTempC());
-  Serial.print("*C\tObject = "); Serial.print(mlx.readObjectTempC()); Serial.println("*C");
-  Serial.print("Ambient = "); Serial.print(mlx.readAmbientTempF());
-  Serial.print("*F\tObject = "); Serial.print(mlx.readObjectTempF()); Serial.println("*F");
-
-  Serial.println();
-  delay(500);
-}


Finalize merger.

Finalize merger.

--- examples/DDS/DDS.ino
+++ examples/DDS/DDS.ino
@@ -34,7 +34,13 @@
 }
 #else // Use the ADC timer instead
 ISR(ADC_vect) {
+  static unsigned char tcnt = 0;
   TIFR1 = _BV(ICF1); // Clear the timer flag
+  if(++tcnt == 4) {
+    digitalWrite(2, HIGH);
+    tcnt = 0;
+  }
   dds.clockTick();
+  digitalWrite(2, LOW);
 }
 #endif


PROGMEM for Arduino, Ard builds, Opcodes can be LONG

--- Arduino/BLuB/BLuB.ino
+++ Arduino/BLuB/BLuB.ino
@@ -7,8 +7,12 @@
 ////////////////////////////////////////////////////////////////////////////////
 // Version history

-#define kBLuBVersion	"v0.05  2013-June-24  yorgle@gmail.com"
-
+#define kBLuBVersion	"v0.06  2013-June-24  yorgle@gmail.com"
+
+// v0.06  2013-June-24  Fixes for Arduino-builds
+//			PROGMEM for low memory usage (ATMega 168)
+//			Opcode parsing: uppercase are skipped, eg PR or PRINT are OK
+//
 // v0.05  2013-June-24  rearranged opcode names, added IC/L
 //			better documentation
 //			added pre-text whitespace elimination
@@ -41,44 +45,82 @@

 ////////////////////////////////////////////////////////////////////////////////
 #ifdef DESKTOP
+// Desktop-based includes
 #include "ardsim.h"		// all of the arduino simulation libraries

+// Desktop defines
+#undef kLocalEcho
+#define kRamSize (RAMEND + 1 )
+
 #else
-
-// arduino includes
+////////////////////////////////////////
+// Arduino includes
 #include <EEPROM.h>  		// EEProm support
 #include <avr/pgmspace.h>	// PGMspace support for strings
+#define kRamSize (RAMEND + 1 )
+
+// Arduino Defines
+#define kLocalEcho (1)
+#define kRamSize ((RAMEND + 1 ) - 920)
+
+// Reclaim more RAM: http://www.adafruit.com/blog/2008/04/17/free-up-some-arduino-sram/
 #endif

+////////////////////////////////////////
+// Common
+
+#define kEESize  (E2END + 1 )
+
+char programRam[ kRamSize ];
+
+#define kNVariables (26)
+int variables[ kNVariables ];
+
+// display runtime trace information
+bool trace = false;
+
+// Parameters for CAll/gosub
+#define kNGosubs (8)
+int gosubLevel = 0;
+char * gosubStack[ kNGosubs ];
+
+// Return values for the opcode handlers
+#define kJRGosubStack	(-6)	/* Stack error for CAll */
+#define kJRDBZError	(-5)	/* Divide by Zero error */
+#define kJRSyntaxError	(-4)	/* general syntax erorr */
+#define kJRStop		(-3)	/* runtime should stop */
+#define kJRNextLine	(-2)	/* runtime should advance to the next line (NOERROR) */
+#define kJRFirstLine	(-1)	/* runtime should start at the first line */
+/* note: 0..Positive numbers are line numbers */

 ////////////////////////////////////////////////////////////////////////////////
-#define kRamSize (E2END + 1 )
-#define kEESize  (E2END + 1 )
-
-#define kNVariables (26)
-
-char programRam[ kRamSize ];
-int variables[ kNVariables ];
-
-int ramFree = 0;
-int eeFree = 0;
-
-bool trace = false;
-
-#define kNGosubs (15)
-char gosubLevel = 0;
-char * gosubStack[ kNGosubs ];
-
-#define kJRGosubStack	(-6)
-#define kJRDBZError	(-5)
-#define kJRSyntaxError	(-4)
-#define kJRStop		(-3)
-#define kJRNextLine	(-2)
-#define kJRFirstLine	(-1)
+// Support for PROGMEM stuff
+
+#ifdef ARDUINO
+// macros to help in doing the PROGMEM string manipulations and displays
+
+// replace Serial.print("string") with SerialPrint("string")
+#define Serialprint(x) SerialPrint_P(PSTR(x))
+void SerialPrint_P(PGM_P str) {
+  for (uint8_t c; (c = pgm_read_byte(str)); str++) Serial.write(c);
+}
+
+#define Serialprintln( x ) \
+        Serialprint( x ); \
+        Serialprint( "\n" );
+
+#else
+////////////////////////////////////////
+// Not arduino
+#define Serialprint( x )  Serial.print( x )
+#define Serialprintln( x ) Serial.println( x )
+#endif
+

 ////////////////////////////////////////////////////////////////////////////////

-#define kBufLen (16)
+// buffer is used for keyboard input, as well as string manipulation routines
+#define kBufLen (32)
 char buffer[kBufLen];

 #define PRINT_LINE( L ) \
@@ -98,6 +140,11 @@
 		|| (*A) == '\t' \
 		|| (*A) == ',' \
 	        ) && (*A) != '\0' ) (A)++; /* parens here are IMPORTANT */
+
+#define SKIP_UPPERCASE( x ) \
+	while(     (*x) >= 'A' \
+		&& (*x) <= 'Z' \
+		&& (*x) != '\0' ) (x)++;

 int myAtoi( char * buf )
 {
@@ -138,52 +185,53 @@

 ////////////////////////////////////////////////////////////////////////////////

+
 void cmd_mem( void )
 {
-	ramFree = strlen( (const char *)programRam );
-	ramFree +=1;
-	ramFree = kRamSize - ramFree;
-
-	Serial.print( "    " );
-	Serial.print( (long)ramFree, DEC );
-	Serial.print( " of " );
+	int rfree = strlen( (const char *)programRam );
+	rfree +=1;
+	rfree = kRamSize - rfree;
+
+	Serialprint( "    " );
+	Serial.print( (long)rfree, DEC );
+	Serialprint( " of " );
 	Serial.print( (long)kRamSize, DEC );
-	Serial.println( " bytes free RAM" );
-
-	// recompute eeFree
+	Serialprintln( " bytes free RAM" );
+
+	// compute EEPROM free space
 	int ch = 'X';

 	// figure out how much is used
-	for( eeFree=0 ; (eeFree<=kEESize) && (ch != '\0') ; eeFree++ )
+	for( rfree=0 ; (rfree<=kEESize) && (ch != '\0') ; rfree++ )
 	{
-		ch = EEPROM.read( eeFree );
+		ch = EEPROM.read( rfree );
 		if( ch == '\0' ) continue;
 	}
-	eeFree = kEESize - eeFree; // turn it into free.
-
-
-	Serial.print( "    " );
-	Serial.print( (long)eeFree, DEC );
-	Serial.print( " of " );
+	rfree = kEESize - rfree; // turn it into free.
+
+
+	Serialprint( "    " );
+	Serial.print( (long)rfree, DEC );
+	Serialprint( " of " );
 	Serial.print( (long)kEESize, DEC );
-	Serial.println( " bytes free EEProm" );
+	Serialprintln( " bytes free EEProm" );
 }

 void cmd_help( void )
 {
-	Serial.println( "BLuB Interface" );
-	Serial.println( kBLuBVersion );
+	Serialprintln( "BLuB Interface" );
+	Serialprintln( kBLuBVersion );
 	cmd_mem();

-	Serial.println( "" );
-	Serial.println( "Available commands:" );
+	Serialprintln( "" );
+	Serialprintln( "Available commands:" );
 	//                   ------- ------- ------- ------- -------
-	Serial.println( "    help    mem     vars    new     list" );
-	Serial.println( "    run     tron    troff" );
+	Serialprintln( "    help    mem     vars    new     list" );
+	Serialprintln( "    run     tron    troff" );
 #ifdef DESKTOP
-	Serial.println( "    files   load    save" );
+	Serialprintln( "    files   load    save" );
 #endif
-	Serial.println( "    elist   eload   esave   enew" );
+	Serialprintln( "    elist   eload   esave   enew" );
 	//                   ------- ------- ------- ------- -------
 }

@@ -200,13 +248,15 @@
 {
   int chp = 0;

+
   // read a line or so into our buffer
   do {
+    while( !Serial.available() );
     buf[chp] = Serial.read();
     if( echoback ) Serial.write( buf[chp] );
     chp++;
-  } while(    Serial.available()
-           && buf[chp-1] != '\n'
+  } while(    //Serial.available()
+           buf[chp-1] != '\n'
            && chp < maxbuf );

   // terminate the buffer
@@ -215,21 +265,21 @@
   // strip newline
   if( chp > 0 && buf[ chp-1 ] == '\n' ) buf[chp-1] = '\0';

-  if( echoback ) Serial.println( "" );
+  if( echoback ) Serialprint( "\n" );
 }

 void cmd_enew( void )
 {
-	Serial.print( "Clearing EEPROM " );
+	Serialprint( "Clearing EEPROM " );
 	for( int i=0 ; i<kEESize ; i++ )
 	{
 		EEPROM.write( i, 0x00 );
 		//    digitalWrite( kLED, i & 0x020 );
-		if( i%64 == 0 ) Serial.print( "." );
-	}
-	Serial.println( " Done." );
+		if( i%64 == 0 ) Serialprint( "." );
+	}
+	Serialprintln( " Done." );
 }

 void cmd_elist( void )
@@ -259,7 +309,7 @@
 	}

 	Serial.print( (long)i, DEC );
-	Serial.println( " bytes loaded from EEPROM." );
+	Serialprintln( " bytes loaded from EEPROM." );
 }

 void cmd_esave( void )
@@ -276,7 +326,7 @@
 	}

 	Serial.print( (long)i, DEC );
-	Serial.println( " bytes saved to EEPROM." );
+	Serialprintln( " bytes saved to EEPROM." );
 }

@@ -296,8 +346,8 @@

 	drp = opendir( kProgramFolder );
 	if( !drp ) {
-		Serial.print( kProgramFolder );
-		Serial.println( ": Unable to read folder." );
+		Serialprint( kProgramFolder );
+		Serialprintln( ": Unable to read folder." );
 		return;
 	}

@@ -361,7 +411,7 @@
 void cmd_vars( void )
 {
 	char buf[20];
-	Serial.println( "Variables:" );
+	Serialprintln( "Variables:" );
 	for( int i=0 ; i<(kNVariables/2) ; i++ )
 	{
 		snprintf( buf, 20, "  %c: %-9d", i+'a', variables[i] );
@@ -385,7 +435,7 @@

 void cmd_list( void )
 {
-	Serial.println( "" );		// newline before
+	Serialprintln( "" );		// newline before
 	Serial.print( programRam );	// dump it all out
 	// no need for println, since program ram ends with newline
 }
@@ -548,6 +598,9 @@
 	// store the opcode, and increment past it.
 	op0 = *line++;
 	op1 = *line++;
+
+	// skip past any decorative uppercase
+	SKIP_UPPERCASE( line );

 	// skip any pre-pended whitespace
 	SKIP_WHITESPACE( line );
@@ -996,7 +1049,7 @@
 		return next;
 	}

-	Serial.println( "Unknown opcode." );
+	Serialprintln( "Unknown opcode." );
 	return kJRStop;
 }

@@ -1026,7 +1079,7 @@
 			bufc = findLine( next );
 			if( *bufc == '\0' ) {
 				Serial.print( (long) next, DEC );
-				Serial.println( ": Line not found." );
+				Serialprintln( ": Line not found." );
 				break;
 			}
 		}
@@ -1046,17 +1099,17 @@

 		// trace output
 		if( trace ) {
-			Serial.print( "Gosub Stack: " );
+			Serialprint( "Gosub Stack: " );
 			Serial.print( (long) gosubLevel, DEC );
-			Serial.println( " items." );
-
-			Serial.print( "Line: " );
+			Serialprintln( " items." );
+
+			Serialprint( "Line: " );
 			char * tc = bufc;
 			while( (*tc) != '\0' && (*tc) != '\n' ) {
 				Serial.write( (const uint8_t*)tc, 1 );
 				tc++;
 			}
-			Serial.println( "" );
+			Serialprintln( "" );

 			// get user input (return)
@@ -1070,21 +1123,21 @@
 		next = evaluate_line( ln, &bufc );

 		if( next == kJRGosubStack ) {
-			Serial.println( "Gosub stack error." );
+			Serialprintln( "Gosub stack error." );
 			next = kJRStop;
 		}
 		if( next == kJRDBZError ) {
-			Serial.println( "Divide By Zero Error." );
+			Serialprintln( "Divide By Zero Error." );
 			next = kJRStop;
 		}
 		if( next == kJRSyntaxError ) {
-			Serial.println( "Syntax Error." );
+			Serialprintln( "Syntax Error." );
 			next = kJRStop;
 		}
 	}

-	Serial.println( "" );
-	Serial.print( "Stopped at line " );
+	Serialprintln( "" );
+	Serialprint( "Stopped at line " );
 	Serial.println( (long)cline, DEC );
 }

@@ -1098,8 +1151,8 @@
 		; // wait for Leonardo to catch up
 	}

-	Serial.println( "BLuB Interface" );
-	Serial.println( kBLuBVersion );
+	Serialprintln( "BLuB Interface" );
+	Serialprintln( kBLuBVersion );
 	cmd_new();
 	init_vars();
 	cmd_mem();
@@ -1138,7 +1191,7 @@
 	}

 	if( verbose )
-		Serial.print( "Error: Line not found." );
+		Serialprint( "Error: Line not found." );
 }

 void cmd_insertLine( char * theLine )
@@ -1151,7 +1204,7 @@

 	if( (pgmSz + newSz) >= kRamSize )
 	{
-		Serial.println( "Out of memory!" );
+		Serialprintln( "Out of memory!" );
 		return;
 	}

@@ -1228,6 +1281,9 @@

 	// get a line of input
 	getSerialLine( linebuf, kLineLen, false );
+#ifdef kLocalEcho
+        Serial.println( linebuf );
+#endif

 	bptr = linebuf;
 	SKIP_WHITESPACE( bptr );


whoops, wrong default (again!)

whoops, wrong default (again!)

--- examples/RF12/RF12demo/RF12demo.ino
+++ examples/RF12/RF12demo/RF12demo.ino
@@ -6,7 +6,7 @@
 // Adding frequency features, author JohnO, 2013-09-05
 // Major EEPROM format change, refactoring, and cleanup for v12, 2014-02-13

-#define RF69_COMPAT 1 // define this to use the RF69 driver i.s.o. RF12
+#define RF69_COMPAT 0 // define this to use the RF69 driver i.s.o. RF12

 #include <JeeLib.h>
 #include <util/crc16.h>


adding new block size and snow white balance

--- firmware/spark-neopixel-control.ino
+++ firmware/spark-neopixel-control.ino
@@ -5,8 +5,8 @@
 //the pin your spark is using to control neopixels
 #define PIXEL_PIN D2
 //the number of pixels you are controlling
-// #define PIXEL_COUNT 467 //giggle
-#define PIXEL_COUNT 150 //colossus
+#define PIXEL_COUNT 467 //giggle
+// #define PIXEL_COUNT 150 //colossus
 //the neopixel chip type
 #define PIXEL_TYPE WS2812B

@@ -105,10 +105,8 @@
         int d = stringToInt(loopArgs[6]);
         int blockSize = stringToInt(loopArgs[7]);

-        buildBlocks(r1, g1, b1, r2, g2, b2, blockSize);
-        delay(d);
-        buildBlocks(r2, g2, b2, r1, g1, b1, blockSize);
-        delay(d);
+        animateBlocks(r2, g2, b2, r1, g1, b1, blockSize, d, true);
+        animateBlocks(r2, g2, b2, r1, g1, b1, blockSize, d, false);
     }
     else if(loopRun.equals(FADECOLOR))
     {
@@ -325,19 +323,19 @@

 int snow()
 {
-    for(int i=0; i<strip.numPixels() / 15; i++)
+    for(int i=0; i<strip.numPixels() / 10; i++)
     { //pick the random pixels
-        uint8_t pix = random(strip.numPixels());
+        int pix = random(strip.numPixels());
         strip.setPixelColor(pix, strip.Color(0, 0, 0));
         strip.show();
         delay(random(50));
     }

-    for(int i=0; i<strip.numPixels() / 15; i++)
+    for(int i=0; i<strip.numPixels() / 10; i++)
     { //pick the random pixels
-        uint8_t pix = random(strip.numPixels());
-        uint8_t brightness = random(255);
-        strip.setPixelColor(pix, strip.Color(brightness, brightness, brightness * .30)); //poor mans white balance
+        int pix = random(strip.numPixels());
+        int brightness = random(255);
+        strip.setPixelColor(pix, strip.Color(brightness, brightness, brightness * .20)); //poor mans white balance
         strip.show();
         delay(random(50));
     }
@@ -354,6 +352,43 @@
         strip.show();
         delay(d);
     }
+}
+
+int animateBlocks(uint8_t r1, uint8_t g1, uint8_t b1,
+    uint8_t r2, uint8_t g2, uint8_t b2, uint8_t blockSize, int d, bool inBlock)
+{
+    for(int j=0; j<blockSize; j++)
+    {
+        for(int i=0; i<strip.numPixels(); i++) {
+            if(i % blockSize == 0)
+            {
+                inBlock = !inBlock;
+            }
+
+            int pix = 0;
+            if( (i + j) >= strip.numPixels())
+            {
+                pix = (i + j) - strip.numPixels();
+            }
+            else
+            {
+                pix = i + j;
+            }
+
+            if(inBlock)
+            {
+                strip.setPixelColor(pix, strip.Color(r1, g1, b1));
+            }
+            else
+            {
+                strip.setPixelColor(pix, strip.Color(r2, g2, b2));
+            }
+        }
+        strip.show();
+        delay(d);
+    }
+
+    return 1;
 }

 int buildBlocks(uint8_t r1, uint8_t g1, uint8_t b1,


Remove non-NMEA debug output

Remove non-NMEA debug output

--- aishling/aishling.ino
+++ aishling/aishling.ino
@@ -16,16 +16,16 @@
   // Give USB terminal time to start up
   startup_message();
   // Set up radio
-  Serial.print("Setting up radio...");
-  unsigned long t;
-  t = millis();
+  //Serial.print("Setting up radio...");
+  //unsigned long t;
+  //t = millis();
   radio_setup();
-  t = millis() - t;
-  Serial.print("done in ");
-  Serial.print(t);
-  Serial.println("ms");
+  //t = millis() - t;
+  //Serial.print("done in ");
+  //Serial.print(t);
+  //Serial.println("ms");

-  radio_test();
+  //radio_test();

   // Connect AIS decoder
   TXLED1; // Green
@@ -38,14 +38,14 @@

 void startup_message() {
   // Startup message
-  Serial.println("AIShling: AIS receiver");
-  Serial.println("http://github.com/going-digital/AIShling");
-  Serial.println();
-  Serial.println("h: help");
-  Serial.println("e: AIS state");
-  Serial.println("f: Radio crystal finetune");
-  Serial.println("q: Enable oscillator output");
-  Serial.println("w: Disable oscillator output");
+  Serial.println("$PAIS, AIShling: AIS receiver                   *60");
+  Serial.println("$PAIS, http://github.com/going-digital/AIShling *4F");
+  //Serial.println();
+  //Serial.println("h: help");
+  //Serial.println("e: AIS state");
+  //Serial.println("f: Radio crystal finetune");
+  //Serial.println("q: Enable oscillator output");
+  //Serial.println("w: Disable oscillator output");
 }

 //////////////////////////////////////////////////////////////////////////////


Integrate bluetooth into project

Integrate bluetooth into project

--- src/src.ino
+++ src/src.ino
@@ -1,4 +1,7 @@
 #include <SPI.h>
+#include <avr/eeprom.h>
+
+#include "Adafruit_BLE_UART.h"

 #include "nokia_5110.h"
 #include "time.h"
@@ -7,8 +10,21 @@
 #include "waypoint_store.h"
 #include "gps.h"

+#define REQ 9
+#define RDY 7
+#define RST 10
+
 #define WAYPOINT_DISTANCE_THRESHOLD 50 /* meters */
 #define BUSY_LED 17
+
+#define GREEN_BUTTON_INTERRUPT_NUM 1 /* corresponds to pin 2 (D2) */
+#define BLUE_BUTTON_INTERRUPT_NUM 0 /* corresponds to pin 3 (D3) */
+
+/* Global flag indicating a button press has not yet been handled.
+   Will be set to 1 on button press, and should be read and cleared
+   atomically (disable/renable interrupts). */
+uint8_t g_green_button_pressed = 0;
+uint8_t g_blue_button_pressed = 0;

 void print_tracking_display(struct tracking_data_t *data)
 {
@@ -48,14 +64,64 @@
     Serial.println((int)b);
 }

+/* todo: standby/active bluetooth and gps
+   make bluetooth interruptable
+   make bluetooth transactions reliable and "transactional" */
 void setup(void)
 {
     /* Initialise LCD - Print startup message */
     lcd_init();
     lcd_clear_display();
+    lcd_write_str("CREAM");
+
+    attachInterrupt(GREEN_BUTTON_INTERRUPT_NUM, green_button_handler, FALLING);
+    attachInterrupt(BLUE_BUTTON_INTERRUPT_NUM, blue_button_handler, FALLING);

     pinMode(BUSY_LED, OUTPUT);

+    int tracking;
+    while (1) {
+        noInterrupts();
+
+        /* handle green button press */
+        if (g_green_button_pressed) {
+            g_green_button_pressed = 0;
+            interrupts();
+
+            run_tracking();
+
+            /* clear all blue presses that occured while in tracking */
+            noInterrupts();
+            g_blue_button_pressed = 0;
+            interrupts();
+
+            lcd_clear_display();
+            lcd_write_str("CREAM");
+        }
+
+        /* handle blue button press */
+        if (g_blue_button_pressed) {
+            g_blue_button_pressed = 0;
+            interrupts();
+
+            run_bluetooth();
+
+            /* clear all green presses that occured while in bluetooth */
+            noInterrupts();
+            g_green_button_pressed = 0;
+            interrupts();
+
+            lcd_clear_display();
+            lcd_write_str("CREAM");
+        }
+
+        interrupts();
+    }
+}
+
+
+void run_tracking(void)
+{
     gps_t gps;
     gps_data_t gps_data;
     gps_initialize(&gps);
@@ -70,9 +136,18 @@
                                          .current_waypoint = initial_waypoint};

     int started = 0;
+    lcd_clear_display();
     lcd_write_str("Pending Fix");

     while (1) {
+
+        noInterrupts();
+        if (g_green_button_pressed) {
+            g_green_button_pressed = 0;
+            interrupts();
+            return;
+        }
+        interrupts();

         if (gps_available(&gps)) {

@@ -155,3 +230,88 @@
 void loop(void)
 {
 }
+
+/* called on button press interrupt */
+void green_button_handler(void)
+{
+    /* only allow button press every 200 ms */
+    static uint32_t last = 0;
+    uint32_t current = millis();
+    if (current - last > 200) {
+        g_green_button_pressed = 1;
+    }
+    last = current;
+}
+
+void blue_button_handler(void)
+{
+    /* only allow button press every 200 ms */
+    static uint32_t last = 0;
+    uint32_t current = millis();
+    if (current - last > 200) {
+        g_blue_button_pressed = 1;
+    }
+    last = current;
+}
+
+void run_bluetooth(void)
+{
+    lcd_clear_display();
+    lcd_write_str("Bluetooth");
+    Adafruit_BLE_UART bluetooth = Adafruit_BLE_UART(REQ, RDY, RST);
+    bluetooth.setDeviceName("PETRICE"); /* 7 characters max! */
+    bluetooth.begin();
+    get_and_store_waypoints(bluetooth);
+}
+
+void get_and_store_waypoints(Adafruit_BLE_UART bluetooth)
+{
+    char buffer[21];
+    uint32_t count, received;
+    float latitude, longitude;
+    uint32_t *eeprom_address = 0;
+
+    /* get count */
+    bluetooth_get_token(bluetooth, buffer);
+    count = atoi(buffer);
+
+    eeprom_write_dword(eeprom_address, count);
+    eeprom_address += 1;
+
+    /* get latitudes and longitudes */
+    for (received = 0; received < count; received++) {
+
+        bluetooth_get_token(bluetooth, buffer);
+        latitude = (float)atof(buffer);
+        eeprom_write_float((float*)eeprom_address, latitude);
+
+        eeprom_address += 1;
+
+        bluetooth_get_token(bluetooth, buffer);
+        longitude = (float)atof(buffer);
+        eeprom_write_float((float*)eeprom_address, longitude);
+
+        eeprom_address += 1;
+    }
+}
+
+/* blocks until data is available from bluetooth */
+aci_evt_opcode_t bluetooth_get_token(Adafruit_BLE_UART bluetooth, char buffer[20])
+{
+    aci_evt_opcode_t status;
+    int pos = 0;
+
+    /* wait for token */
+    while (!bluetooth.available()) {
+        bluetooth.pollACI();
+        status = bluetooth.getState();
+    }
+
+    /* read token into buffer */
+    while (bluetooth.available()) {
+        buffer[pos++] = bluetooth.read();
+    }
+    buffer[pos] = '\0';
+
+    return status;
+}


add jacobian

add jacobian

--- arduino/opencr_arduino/opencr/libraries/OpenManipulator/example/Arduino/Test/kinematics/kinematics.ino
+++ arduino/opencr_arduino/opencr/libraries/OpenManipulator/example/Arduino/Test/kinematics/kinematics.ino
@@ -1,13 +1,13 @@
 #include <OMManager.h>
 #include <OMMath.h>
 #include <OMKinematics.h>
+#include <OMDebug.h>

 #include <Eigen.h>

 #define X_AXIS MATH::makeVector3(1.0, 0.0, 0.0)
 #define Y_AXIS MATH::makeVector3(0.0, 1.0, 0.0)
 #define Z_AXIS MATH::makeVector3(0.0, 0.0, 1.0)
-

 #define WORLD 0
 #define COMP1 1
@@ -21,11 +21,12 @@
 void setup()
 {
   Serial.begin(57600);
-  while (!Serial);
+  while (!Serial)
+    ;

   Manipulator manipulator;
   manipulator.addWorld(WORLD, COMP1);
-  manipulator.addComponent(COMP1, WORLD, COMP2, MATH::makeVector3(-0.100, 0.0, 0.0), IDENTITY_MATRIX, 1, Z_AXIS, 0.5, MATH::makeMatrix3(1,1,1,1,1,1,3,1,1));
+  manipulator.addComponent(COMP1, WORLD, COMP2, MATH::makeVector3(-0.100, 0.0, 0.0), IDENTITY_MATRIX, 1, Z_AXIS, 0.5, MATH::makeMatrix3(1, 1, 1, 1, 1, 1, 3, 1, 1));
   manipulator.addComponent(COMP2, COMP1, COMP3, MATH::makeVector3(0.0, 0.0, 0.050), IDENTITY_MATRIX, 2, Y_AXIS, 1.5);
   manipulator.addComponentChild(COMP2, COMP4);
   manipulator.addComponent(COMP3, COMP2, COMP4, MATH::makeVector3(0.0, 0.050, 0.0), IDENTITY_MATRIX, NONE);
@@ -33,6 +34,9 @@
   manipulator.addTool(TOOL, COMP4, MATH::makeVector3(0.0, 0.0, 0.025), IDENTITY_MATRIX, 4, 0.1);

   // manipulator.checkManipulatorSetting();
+
+  Eigen::MatrixXf jacobian = KINEMATICS::CHAIN::jacobian(&manipulator, TOOL);
+  PRINT::MATRIX(jacobian);
 }

 void loop()