diff --git a/TODO b/TODO
new file mode 100644
index 0000000000000000000000000000000000000000..5e7940e189e38e385a9770a2147d96c63e5950d7
--- /dev/null
+++ b/TODO
@@ -0,0 +1,4 @@
+Package - https://github.com/Debian/dh-make-golang
+
+Writing data to device: https://golang.org/pkg/encoding/binary/
+Also: https://github.com/tarm/serial
diff --git a/devices/geiger/gqgmc.go b/devices/geiger/gqgmc.go
index 73e4483044eb47681ee8c8116c501b1daa4a3a7a..18b6b537518a2d2507ba903df8720b0b2d98fa0d 100644
--- a/devices/geiger/gqgmc.go
+++ b/devices/geiger/gqgmc.go
@@ -7,19 +7,946 @@
 
 package geiger
 
+import (
+	"time"
+
+	"github.com/tarm/serial"
+)
+
+const (
+	powerOnOff                    = 0
+	alarmOnOff                    = 1
+	speakerOnOff                  = 2
+	graphicModeOnOff              = 3
+	backlightTimeoutSeconds       = 4
+	idleTitleDisplayMode          = 5
+	alarmCPMValue                 = 6
+	calibrationCPM0               = 8
+	calibrationSvUc0              = 10
+	calibrationCPM1               = 14
+	calibrationSvUc1              = 16
+	calibrationCPM2               = 20
+	calibrationSvUc2              = 22
+	idleDisplayMode               = 26
+	alarmValueuSvUc               = 27
+	alarmType                     = 31
+	saveDataType                  = 32
+	swivelDisplay                 = 33
+	zoom                          = 34
+	dataSaveAddress               = 38
+	dataReadAddress               = 41
+	nPowerSavingMode              = 44
+	nSensitivityMode              = 45
+	nCounterDelay                 = 46
+	nVoltageOffset                = 48
+	maxCPM                        = 49
+	nSensitivityAutoModeThreshold = 51
+	saveDate                      = 52
+	saveTime                      = 55
+	maxBytes                      = 58
+)
+
+var configBytes = map[int]int{
+	powerOnOff:              1,
+	alarmOnOff:              1,
+	speakerOnOff:            1,
+	graphicModeOnOff:        1,
+	backlightTimeoutSeconds: 1,
+	idleTitleDisplayMode:    1,
+	alarmCPMValue:           2,
+	calibrationCPM0:         2,
+	calibrationSvUc0:        4,
+	calibrationCPM1:         2,
+	calibrationSvUc1:        4,
+	calibrationCPM2:         2,
+	calibrationSvUc2:        4,
+	idleDisplayMode:         1,
+	alarmValueuSvUc:         4,
+	alarmType:               1,
+	saveDataType:            1,
+	swivelDisplay:           1,
+	zoom:                    4,
+	dataSaveAddress:         3,
+	dataReadAddress:         3,
+	nPowerSavingMode:        1,
+	nSensitivityMode:        1,
+	nCounterDelay:           2,
+	nVoltageOffset:          1,
+	maxCPM:                  2,
+	nSensitivityAutoModeThreshold: 1,
+	saveDate:                      3,
+	saveTime:                      3,
+	maxBytes:                      1,
+}
+
+const (
+	saveOff = iota
+	saveCPS
+	saveCPM
+	saveCPH
+	saveMax
+)
+
+const (
+	key1 = iota
+	key2
+	key3
+	key4
+)
+
+const (
+	historyDataMaxSize = 0x1000
+	historyAddrMaxSize = 0x10000
+	forFirmware = 2.23
+	kNVMSize = 256
+)
+
+const (
+cmdGetSerial        = "<GETSERIAL>>"
+cmdGetVersion       = "<GETVER>>"
+cmdGetVoltage       = "<GETVOLT>>"
+cmdGetCpm           = "<GETCPM>>"
+cmdGetCps           = "<GETCPS>>"
+cmdGetCfg           = "<GETCFG>>"
+cmdEraseCfg         = "<ECFG>>"
+cmdUpdateCfg        = "<CFGUPDATE>>"
+cmdTurnOnCps       = "<HEARTBEAT1>>"
+cmdTurnOffCps      = "<HEARTBEAT0>>"
+cmdTurnOffPwr      = "<POWEROFF>>"
+)
+
+const (
+    errOpen = "Failed to open USB port"
+    errFirmware = "GQ GMC has older firmware.  Some commands may not work."
+    errVersion = "Failed to read the version number of the firmware"
+    errSerialNumber = "Failed to read the serial number "
+    errCPM = "Failed to read the counts per minute "
+    errCPS = "Failed to read the counts per second "
+    errAutoCPS = "Failed to read auto counts per second "
+    errCFG = "Failed to get configuration data "
+    errEraseCFG = "Failed to erase configuration data "
+    errUpdateCFG = "Failed to update configuration data "
+    errClear = "Failed to clear USB input buffer. You should power cycle GQ GMC."
+    errBatteryVoltage = "Failed to read the battery voltage "
+    errHistoryData = "Failed to read the history data "
+    errHistoryDataLengthFmt = "Requested data length of the history command cannot exceed %d bytes"
+    errHistoryDataAddressFmt = "Address of the history command cannot exceed %d bytes"
+    errHistoryDataOverrunFmt = "History data length added to the address cannot exceed %d bytes"
+    errYear = "Failed to set year"
+    errMonth = "Failed to set month"
+    errDay = "Failed to set day"
+    errHour = "Failed to set hour"
+    errMinute = "Failed to set minute"
+    errSecond = "Failed to set second"
+    )
+
+// CONFIGURATION DATA
+//
+// Setting the configuration data of the GQ GMC is not a
+// straight forward procedure. The following statement is the
+// principle reason why: the GQ GMC does not use or keep a RAM copy
+// of its non-volatile memory (NVM) (configuration data is in NVM).
+// That condition coupled with the fact that the EEPROM
+// used by the GQ GMC can only be reprogrammed
+// all 256 bytes at a shot means that if you write a byte of
+// configuration data and then read back the configuration data,
+// you will not see your data changed as expected.
+//
+// All this means that in order to change the configuration
+// parameters and have the GQ GMC change its operations accordingly,
+// 1) the host computer must keep its own copy of NVM,
+// 2) update its own copy of NVM,
+// 3) issue the erase configuration command,
+// 4) write all 256 bytes of configuration data at one shot,
+// 5) follow immediately with an update configuration command.
+//
+// When the GQ GMC receives the update configuration command,
+// then and only then does it re-configure its operation in
+// accordance with the NVM configuration data. Keeping the host
+// computer's copy of the NVM accurate and up to date can be
+// problematic since behind the back of the host computer,
+// the GQ GMC can be changed manually.
+//
+// The GQGMC software makes a valiant attempt to hide all this
+// from the user. First, immediately following the opening of
+// the USB port, the software silently reads the configuration
+// data from the GQ GMC to obtain its own copy of NVM.
+// From that point on, it is assumed that no manual changes
+// to the GQ GMC will occur. The GQGMC software then reads/writes
+// it own local copy of NVM. When the user issues the Update CFG
+// command, the GQGMC software silently
+// 1) issues the erase configuraton command,
+// 2) writes all 256 bytes of NVM,
+// 3) issues the update configuration command.
+
+// The user software may at any time cause a Get configuration
+// command in which case, the user must be aware that the GQGMC's
+// local copy of NVM will be overwritten.
+
+
+// getConfigurationData public method reads configuration data. You
+// don't request pieces of the configuration data, all 256 bytes
+// are returned, although, there are currently only about 60
+// bytes used (corresponding to about 50 parameters). The command is
+// get_cfg_cmd (see GQ GMC COMMANDS above).
+void
+func (gc *GQGMCCounter) getConfigurationData()
+{
+  // Issue command to get configuration and read returned data.
+  communicate(get_cfg_cmd, reinterpret_cast<char *>(&mCFG_Data),
+                           sizeof(mCFG_Data));
+
+  // If read of returned data failed, set error code.
+  if (mRead_status == false)
+  {
+    mError_code = eGet_CFG;
+  }
+
+  //  debugging code
+  /*
+  uint8_t * inp = (uint8_t *)&mCFG_Data;
+  for(uint32_t i=0; i<64; i++)
+  {
+    cout << Hex(inp[i]) << "-";
+    if (i > 0)
+      if (((i+1)%16) == 0) cout << endl;
+    if (i > 62)break;
+  }
+  cout << endl;
+  */
+  // end debug code
+
+  return;
+} // end getConfigurationData()
+
+// The following get methods are provided in order to access the
+// configuration data, not all configuration data, but only those
+// parameters which are needed to retrieve and parse the history data.
+
+// getSaveDataType is a get method to retrieve the saved data type
+// parameter in the configuration data. Note that SaveDataType is
+// retrieved from the host computer's local copy of NVM
+// configuration data. The return type is an enumeration
+// which matches the following possibilities:
+// 0 = logging is off,
+// 1 = counts per second,
+// 2 = counts per minute,
+// 3 = CPM averaged per hour.
+enum saveDataType_t
+func (gc *GQGMCCounter) getSaveDataType()
+{
+  return ((enum saveDataType_t)(mCFG_Data.saveDataType));
+} // end getSaveDataType()
+
+
+// setSaveDataType is a set method to reconfigure the data type
+// logged in the history buffer. This method is provided as a
+// convenience instead of using the writeConfigurationData method
+// since changing the saved data type is considered to be
+// more commonly used configuration change. The passed argument
+// is an enumeration (see definition in gqgmc.hh) whose value
+// is to be the new value of the saveDataType configuration
+// parameter. Note that only the host computer's local copy
+// of NVM is updated.  The user must issue a update configuration
+// command to cause the GQGMC to implement the NVM changes.
+void
+func (gc *GQGMCCounter) setSaveDataType(enum saveDataType_t newSaveDataType)
+{
+  uint8_t  saveData = uint8_t(newSaveDataType);
+
+  // Use writeConfigurationData method
+  writeConfigurationData(eSaveDataType, eSaveDataType_bytecnt, &saveData);
+  // error condition will be handled by writeConfigurationData()
+
+  return;
+} // end setSaveDatatype method
+
+
+// getDataSaveAddress is get method to retrieve the address
+// in the history buffer where the logged data begins. See
+// getHistoryData method for an explanation of the
+// dataSaveAddress in the configuration data structure.
+// The returned value is a 32 bit address, although the
+// dataSaveAddress maximum value cannot exceed 24 bits worth.
+// Note that the DataSaveAddress is retrieved from the host
+// computer's local copy of the GQ GMC's NVM configuration data.
+uint32_t
+func (gc *GQGMCCounter) getDataSaveAddress()
+{
+  uint32_t      address(0);
+
+  address |= (uint32_t(mCFG_Data.dataSaveAddress2) << 16);
+  address |= (uint32_t(mCFG_Data.dataSaveAddress1) <<  8);
+  address |= (uint32_t(mCFG_Data.dataSaveAddress0) <<  0);
+
+  return address;
+}  // end getDataSaveAddress()
+
+// The resetDataSaveAddress sets the dataSaveAddress configuration
+// parameter to the value of 0x10.  This is provided as a
+// convenience instead of using writeConfigurationData() directly
+// because setting the start of the history buffer back to zero
+// would be a common thing to do. Note that the DataSaveAddress
+// is being updated in the host computer's local copy of the
+// GQ GMC's NVM configuration data. The user must issue the
+// update configuration command to force the GQ GMC to implement
+// the NVM configuration data changes.
+void
+func (gc *GQGMCCounter) resetDataSaveAddress()
+{
+  uint32_t     address(0x10); // 0x10 provides room for date/timestamp
+
+  // Use writeConfigurationData() method
+  writeConfigurationData(eDataSaveAddress, eDataSaveAddress_bytecnt,
+                         (uint8_t *)(&address));
+  // error condition handled by writeConfigurationData()
+
+  return;
+} // end resetDataSaveAddress()
+
+
+// writeConfiguratonData is the public method to write configuration
+// data. It takes the following parameters.
+//
+// cfgParameter is actually the offset from the beginning of the
+// configuration data of the desired parameter. It was explicitly
+// created this way and assigned the offset as its enumeration value so
+// that cfgParameter serves both as an enumeration and as the actual
+// address of the configuration parameter.
+//
+// cfgData is a pointer to an array of raw binary for the parameter.
+//
+// cfgDataCount is the number of bytes of cfgData. Since cfgData is
+// passed as pointer, we need to supply the array length separately
+// as the cfgDataCount parameter.
+//
+// Note that this method updates the local copy of the GQ GMC's
+// NVM configuration data. As noted previously in the documentation,
+// the GQ GMC does not support a direct method of updating its
+// NVM configuration data and having it take effect immediately.
+//
+// This method is not an exact reflection of the native GQ GMC write
+// configuration command. The native GQ GMC write configuration
+// only writes one byte at a time. So writing multibyte configuration
+// parameters would take multiple writes, one per data byte. Instead,
+// we abstract the write configuration command so the user does not
+// have to know this much detail. We can do this because we
+// know a priori the base address of each parameter and how many
+// bytes each parameter needs. So this method is intended to
+// handle parameters with multibyte data by requiring the user
+// to only pass the parameter enumeration, its byte count, and
+// value.
+//
+// Note that changes to the configuration data do not have
+// immediate effect since we writing to the local copy of the
+// GQ GMC's NVM configuration data. To take effect, the user must
+// call the updateConfigurationData() method. Before doing so, all
+// changes to the configuration data should be completed so that
+// interdependent configuration parameters are updated
+// simultaneously.
+void
+func (gc *GQGMCCounter) writeConfigurationData(enum cfg_param_t       cfgParameter,
+                              enum cfg_bytecnt_t     cfgDataCount,
+                              uint8_t const * const  cfgData)
+{
+  uint8_t * pCfg_Data = (uint8_t *)&mCFG_Data + uint8_t(cfgParameter);
+  for(int i=0; i<cfgDataCount; i++)
+  {
+    // Convert little endian to big endian which GQ GMC wants.
+    if (mBig_endian)
+      pCfg_Data[i] = cfgData[i];
+    else
+      pCfg_Data[i] = cfgData[cfgDataCount-1-i];
+  } // end for loop
+
+  return;
+} // end writeConfigurationData()
+
+// loadConfigurationData private method writes all 256 bytes
+// of the configuration data to the GQ GMC. This will take
+// over a minute to complete. This is a practice in patience.
+// The GQ GMC's write_cfg_cmd only transmits a single byte
+// at a time. So it takes 256 transmits and each transmit
+// has to wait for a 0xAA return.  The user obviously should
+// not update the NVM configuration too often.
+void
+func (gc *GQGMCCounter) loadConfigurationData()
+{
+  const
+  uint32_t     retsize = 1;
+  char         ret_char[retsize+1];
+
+  // Need a pointer to the local host computer's copy
+  // of the NVM configuration data.
+  uint8_t *    pCfg_Data = (uint8_t *)&mCFG_Data;
+
+  // Begin formulating the write configuration data command.
+  // "AD" is just a place holder for the address byte and data byte
+  // that will be dynamically derived and inserted.
+  string write_cfg_cmd = "<WCFGAD>>";
+
+  // The parameter and its data have to be dynamically derived.
+  // write_cfg_cmd[5] is parameter enumeration (aka address offset)
+  // write_cfg_cmd[6] is parameter data
+
+  // Pack address and data into write_cfg_data_cmd with big
+  // endian byte order.
+
+  // Address (ie, parameter) is less than 256 since configuration
+  // data has a fixed size of 256 bytes, so address is one byte.
+
+  // pack address and data into command
+  for(uint16_t i=0; i<kNVMSize; i++)
+  {
+    // Increment the address for each additional data byte.
+    write_cfg_cmd[5] = uint8_t(i);
+
+    // Load data one byte at a time
+    write_cfg_cmd[6] = pCfg_Data[i];
+
+/*    // debug code
+    if (i < 64)
+    {
+      for(int i=0; i<5; i++)
+        cout << write_cfg_cmd[i];
+      cout << Hex(write_cfg_cmd[5]);
+      cout << Hex(write_cfg_cmd[6]);
+      cout << write_cfg_cmd[7];
+      cout << write_cfg_cmd[8];
+      cout << endl;
+    }
+*/    // end debug code
+
+    // Issue command to write configuration data, one byte
+    // at a time because that is the native write configuration
+    // command of the GQ GMC.
+    communicate(write_cfg_cmd, ret_char, retsize);
+
+    // if read of returned data succeeded, convert raw data to float
+    if (mRead_status == true)
+    {
+      // We really don't care about the return value of 0xAA. If the
+      // GQ GMC does not recognize the command, it returns nothing and
+      // we get a read_status error.
+    }
+    else  // else for failure, set error code
+    {
+      mError_code = eWrite_CFG;
+      break;                    // break out of for loop
+    } // end (read_status == true)
+  } // end for loop
+
+  return;
+} // loadConfigurationData()
+
+// eraseConfigurationData public method erases the configuration data
+// in its entirety. The configuration returns to its factory default
+// setting. It might have been better to call this the reset
+// configuration data command. The command is erase_cfg_cmd
+// (see GQ GMC COMMANDS above).
+void
+func (gc *GQGMCCounter) eraseConfigurationData()
+{
+  const
+  uint32_t     retsize = 1;
+  char         ret_char[retsize+1];
+
+  // Issue command to erase NVM configuration.
+  communicate(erase_cfg_cmd, ret_char, retsize);
+
+  // If read of returned data succeeded, convert raw data to float,
+  if (mRead_status == true)
+  {
+    // We really don't care about the return value of 0xAA. If the
+    // GQ GMC does not recognize the command, it returns nothing and
+    // we get a read_status error.
+  }
+  else  // else for failure, set the error code.
+  {
+    mError_code = eErase_CFG;
+  }
+
+  return;
+} // end eraseConfigurationData()
+
+
+// The updateConfigurationdata public method is called to make changes
+// to configuration data take effect. All other methods to modify
+// the configuration data do not cause the GQ GMC to immediately
+// change operation. This would not be desireable since various
+// changes to the configuration may be interdependent and so
+// we would want the changes to take effect simultaneously to
+// insure proper operation. There are no arguments to call.
+// The command is update_cfg_cmd (see GQ GMC COMMANDS above).
+// The user who calls this method may want to pop-up a window
+// stating that this will take about one minute. That is about
+// how long it will take to write all 256 bytes to the GQ GMC.
+// This method calls eraseConfigurationData() and
+// loadConfigurationData() as part of the procedure needed to
+// force the GQ GMC to implement operational changes per the
+// new NVM configuration data.
+void
+func (gc *GQGMCCounter) updateConfigurationData()
+{
+  const
+  uint32_t     retsize = 1;
+  char         ret_char[retsize+1];
+
+    // 1st, we have to erase configuration data
+  // cout << erase_cfg_cmd << endl; // debug
+  eraseConfigurationData();
+  // 2nd, write all 256 bytes of NVM to GQ GMC
+  // cout << "load cfg" << endl; // debug
+  loadConfigurationData();
+
+  // cout << update_cfg_cmd << endl; // debug
+  // Issue command to update NVM and force GQ GMC to change
+  // operation in accordance to new configuration data.
+  communicate(update_cfg_cmd, ret_char, retsize);
+
+  // If read of returned data succeeded, convert raw data to float,
+  if (mRead_status == true)
+  {
+    // We really don't care about the return value of 0xAA. If the
+    // GQ GMC does not recognize the command, it returns nothing and
+    // we get a read_status error.
+  }
+  else  // else for failure, set the error code.
+  {
+    mError_code = eUpdate_CFG;
+  }
+
+  return;
+} // end updateConfigurationData()
+
+
+// sendKey is the public method to emulate any one of the 4 keys on
+// the front panel of the GQ GMC. The front panel has a 'left arrow',
+// 'up arrow, 'down arrow', and 'enter' keys. These are used to
+// navigate through the GQ GMC's menu system. In principle, the
+// menu system can be used to set virtually any and all of the
+// configuration data (although this is not recommended for
+// such configuration data as the calibration values).
+// So instead of the writeConfigurationData method,
+// the proper sequence of sending the keys would do the
+// same thing. The command is derived dynamically, but the actual
+// command is "<KEY0>>" or "<KEY1>>" or "<KEY2>>" or "<KEY3>>".
+// So for the purpose that the user need not know the actual
+// command string, the softkey_t enumeration is created and used
+// as the passed argument to the method. See the enum softkey_t
+// declaration in gqgmc.hh for more discussion.
+//
+// For successive sendKey calls there is a trick to know when
+// using the sendKey method. The trick is you can't
+// transmit sendKey too fast and you can't do it too slow.
+// Another thing is that the Save Data option menu starts with
+// the current data type and then cycles through the other options.
+// So you have to know what is the current data type and
+// then send the Enter key the proper number of times to cycle
+// to the desired option. When moving through the menu we use
+// 0.5 seconds, but when moving through a pop up options menu
+// we have to move faster and so should use 0.25 seconds
+// between sendKey in that context.
+void
+func (gc *GQGMCCounter) sendKey(enum softkey_t key)
+{
+  char   inp[1]; // This will not be used, just needed as dummy arg
+
+  // Begin formulating the send key command.
+  string keycmd = "<KEY";
+
+  // Append key number which is an enumeration equal to the
+  // ASCII value of the key, ie, '0', '1', '2', or '3'.
+  keycmd += uint8_t(key);
+  // Append ">>"
+  keycmd += ">>";
+
+  communicate(keycmd, inp, 0);  // no return data
+  // Since the sendkey command returns no data there is no way to
+  // test success of communication.
+
+  // Debug code
+/*
+  for(int i=0; i<7; i++)
+    cout << Hex(keycmd[i]);
+  cout << endl;
+*/
+  return;
+} // end sendKey()
+
+
+// setDate is the public method to set the date. The date is passed as
+// an ASCII string with the format of <month><day><year>, for example,
+// 112312 is November (11th month) 12, 2012.  The year is specified
+// as the last two digits of the century since presumably the date is
+// is being set to the current date. In reality, the GQ GMC has a separate
+// command for setting each of the month, day, and year.
+void
+func (gc *GQGMCCounter) setDate(string date)
+{
+  const
+  uint32_t     retsize = 1;
+  char         ret_char[retsize+1];
+
+  // The date is broken up into three separate commands one each for
+  // month, day, and year as supported by the GQ GMC.
+
+  // Set the month, <SETDATEMMXX>> where XX = month byte.
+  {
+    // uint16_t is necessary since ss >> uint8_t does not work.
+    uint16_t      month=0;
+    string        setMonthCmd;
+    stringstream  ss;
+    ss << date[0] << date[1];
+    ss >> month;
+    //cout << "month = " << Hex(uint8_t(month)) << endl;
+    setMonthCmd  = "<SETDATEMM";
+    setMonthCmd += uint8_t(month);
+    setMonthCmd += ">>";
+    communicate(setMonthCmd, ret_char, retsize);
+  }
+
+  // Set the day, <SETDATEDDXX>> where XX = day byte.
+  {
+    uint16_t      day=0;
+    string        setDayCmd;
+    stringstream  ss;
+    ss << date[2] << date[3];
+    ss >> day;
+    //cout << "day = " << Hex(uint8_t(day)) << endl;
+    setDayCmd  = "<SETDATEDD";
+    setDayCmd += uint8_t(day);
+    setDayCmd += ">>";
+    communicate(setDayCmd, ret_char, retsize);
+  }
+
+  // Set the year, <SETDATEYYXX>> where XX = year byte.
+  {
+    uint16_t      year=0;
+    string        setYearCmd;
+    stringstream  ss;
+    ss << date[4] << date[5];
+    ss >> year;
+    //cout << "year = " << Hex(uint8_t(year)) << endl;
+    setYearCmd  = "<SETDATEYY";
+    setYearCmd += uint8_t(year);
+    setYearCmd += ">>";
+    communicate(setYearCmd, ret_char, retsize);
+  }
+
+  return;
+} // end set Date()
+
+// setTime is the public method to set the time of day. The time is
+// passed as an ASCII string with the format of <hour><minutes><seconds>,
+// for example, 142256 is the 14th hour, 22 minutes after the hour,
+// 56 seconds after the minute.  The hour is given in 24 hour format
+// counting from 0 to 23. In reality, the GQ GMC provides a separate
+// command for setting each of the hour, minutes and seconds.
+void
+func (gc *GQGMCCounter) setTime(string time)
+{
+    const
+    uint32_t     retsize = 1;
+    char         ret_char[retsize+1];
+
+    // The time is broken up into three separate commands one each for
+    // hour, minute, and second as supported by the GQ GMC.
+
+    // Set the hour, <SETTIMEHHXX>> where XX = hour byte.
+    {
+      uint16_t      hour=0;       // stringstream does not convert to uint8_t
+      string        setHourCmd;
+      stringstream  ss;
+      ss << time[0] << time[1];
+      ss >> hour;
+      //cout << "hours = " << Hex(uint8_t(hour)) << endl;
+      setHourCmd  = "<SETTIMEHH";
+      setHourCmd += uint8_t(hour);
+      setHourCmd += ">>";
+      communicate(setHourCmd, ret_char, retsize);
+    }
+
+    // Set the minute, <SETTIMEMMXX>> where XX = minute byte.
+    {
+      uint16_t      minute=0;
+      string        setMinuteCmd;
+      stringstream  ss;
+      ss << time[2] << time[3];
+      ss >> minute;
+      //cout << "minute = " << Hex(uint8_t(minute)) << endl;
+      setMinuteCmd  = "<SETTIMEMM";
+      setMinuteCmd += uint8_t(minute);
+      setMinuteCmd += ">>";
+      communicate(setMinuteCmd, ret_char, retsize);
+    }
+
+    // Set the seconds, <SETTIMESSXX>> where XX = second byte.
+    {
+      uint16_t      second=0;
+      string        setSecondCmd;
+      stringstream  ss;
+      ss << time[4] << time[5];
+      ss >> second;
+      //cout << "second = " << Hex(uint8_t(second)) << endl;
+      setSecondCmd  = "<SETTIMESS";
+      setSecondCmd += uint8_t(second);
+      setSecondCmd += ">>";
+      communicate(setSecondCmd, ret_char, retsize);
+    }
+
+  return;
+} // end setTime()
+
+
+// PRIVATE METHODS
+
+// communicate private method is used to write/read data to/from
+// the GMC-300. This method is expressedly designed to be called
+// by methods which send an ASCII string and expect to receive
+// returned data. However for flexibility, if the command string
+// is null, no command is transmitted and if the expected number
+// of return bytes is zero, no read is performed.
+// cmd is the ASCII string command.
+// retdata is the repository for the returned data.
+// retbytes is the number of bytes of returned data.
+void
+func (gc *GQGMCCounter) communicate(const string cmd, char * retdata, uint32_t retbytes)
+{
+  // Clear the USB port of any left over data from last exchange. Even
+  // though we know how many bytes the GQ GMC transmits for each
+  // command, experience has shown this is the safe thing to do since
+  // there is no protocol for the returned data.
+  clearUSB();
+
+  //cout << cmd << endl;
+  // 1st, issue the command to the GMC-300, this is always an ASCII
+  // string.
+  // For flexibility, only transmit if cmdbytes is not 'null'.
+  if (cmd.size() > 0) sendCmd(cmd);
+  // 2nd, read the return data, for all commands except get version
+  // this is always raw binary data.
+  // For flexibility, only read if return is not 'null'.
+  if (retbytes > 0) readCmdReturn(retdata, retbytes);
+
+  return;
+} // end communicate()
+
+// sendCmd is the private method (the basic method) to transmit
+// the command to the GMC-300.
+// cmd is the ASCII string to send as the command.
+void
+func (gc *GQGMCCounter) sendCmd(const string cmd)
+{
+  // This is a common place to reset the error code since it is always
+  // called for any command.
+  mError_code = eNoProblem;
+
+  // This is a common place to reset the read status since every read
+  // is always preceeded by a write command (except for turn_on_cps!).
+  mRead_status = true;
+
+  // Call low level C stdio routine to write to USB port.
+  write(mUSB_serial, cmd.c_str(), cmd.size());
+
+  return;
+} // end sendCmd()
+
+// readCmdReturn is the private method (the basic method) to read
+// the return bytes from the command.
+// retdata is the repository for the returned data.
+// retbytes is the number of bytes of the returned data.
+void
+func (gc *GQGMCCounter) readCmdReturn(char * retdata, uint32_t retbytes)
+{
+  uint32_t rcvd = 0;           // the number of received bytes
+  char * inp    = &retdata[0]; // pointer to returned data char array
+                               // start pointer off at beginning of
+                               // repository.
+
+  // Assume read will succeed, replicated here only because of the
+  // nature of the turn_on_cps command which automatically returns
+  // data without a preceeding write.
+  mRead_status = true;
+
+  // Now read the returned raw byte string. Do this by reading one byte
+  // at a time until the requested number of bytes are attained. However,
+  // the serial port has been setup to timeout each read attempt. So if
+  // after N calls to read, we haven't yet read all N bytes, declare
+  // a failure. The read is done this way to avoid an indefinite blocking
+  // situation when 0 bytes are returned by the GQ GMC. The only good thing
+  // about this methodology is that the largest possible read is only 4K
+  // for the history data. So the read never really takes that much time.
+  for(uint32_t i=0; i<retbytes; i++)
+  {
+    rcvd += read(mUSB_serial, inp, 1);
+    inp   = &retdata[rcvd];
+    if (rcvd >= retbytes) break;
+  } // end for loop
+
+  //  debugging code
+  /*
+  inp = &retdata[0];
+  for(uint32_t i=0; i<retbytes; i++)
+  {
+    cout << Hex(inp[i]) << "-";
+    if (i > 0)
+      if (((i+1)%16) == 0) cout << endl;
+    if (i > 62)break;
+  }
+  cout << endl;
+  cout << "rcvd = " << rcvd << endl;
+  */
+  // end debug code
+
+  // Communication is considered a failure if less than the expected
+  // number of bytes is returned by the GMC-300.
+  if (rcvd < retbytes)
+    mRead_status = false;
+
+  return;
+} // readCmdReturn()
+
 // GQGMCCounter is a GQ GMC Counter
 type GQGMCCounter struct {
 	fh string // TODO: make this a file handle.
+	config serial.Config
 }
 
 // NewGQGMC creates a new GQGMC Counter instance
 func NewGQGMC(c Config) (*GQGMCCounter, error) {
-	return &GQGMCCounter{
-		fh: "TODO",
-	}, nil
+	var gc GQGMCCounter
+
+	portCfg := serial.Config {
+		Name: c.Device,
+		Baud: 57600,
+		ReadTimeout: 500 * time.Millisecond,
+	}
+	gc.port = OpenPort(portCfg)
+	//vers := getVersion()
+        //getConfigurationData()
+	return &gc, nil
+}
+
+// Clear clears out any remaining data
+func (gc *GQGMCCounter) Clear() error {
+	// Read up to 10 chars until nothing comes back.
+	// error otherwise.
+	return nil
+}
+
+// Version gets the version of the device
+func (gc *GQGMCCounter) Version() (string, error) {
+  //communicate(get_version_cmd, version, versize);
+  // use cmdGetVersion. Returns 14 byte string.
+  return "", nil
+}
+
+// SerialNum gets the serial number of the device
+func (gc *GQGMCCounter) SerialNum() (string, error) {
+  //communicate(get_serial_cmd, serial_number, sernumsize);
+  // use cmdGetSerial. Returns 7 bytes.
+  // Turn each 4 bits into corresponging hex char.
+      bs := []byte{0, 0x30, 0, 0xE3, 0x4A, 0x35, 0x1A}
+          for _, b := range bs {
+		          fmt.Printf("%02X", b)
+			      }
+			          fmt.Println("")
+  return "", nil
+}
+
+// GetCPM returns CPM
+func (gc *GQGMCCounter) GetCPM() (uint16, error) {
+	//uint32_t cpmsize = 2;          // 2 bytes of returned data
+	//communicate(get_cpm_cmd, cpm_char, cpmsize);
+	// 1st byte is MSB, but note that upper two bits are reserved bits.
+	// Note that shifting and bitmasking performed in uP register, so
+	// endianess is irrevelant.
+	//cpm_int |= ((uint16_t(cpm_char[0]) << 8) & 0x3f00);
+	//cpm_int |=  (uint16_t(cpm_char[1]) & 0x00ff);
+	return 0, nil
+}
+
+// GetCPS returns CPS
+func (gc *GQGMCCounter) GetCPS() (uint16, error) {
+	//uint32_t cpssize = 2;          // 2 bytes of returned data
+	//communicate(get_cps_cmd, cps_char, cpssize);
+	// 1st byte is MSB, but note that upper two bits are reserved bits.
+	// Note that shifting and bitmasking performed in uP register, so
+	// endianess is irrevelant.
+	//cps_int |= ((uint16_t(cps_char[0]) << 8) & 0x3f00);
+	//cps_int |=  (uint16_t(cps_char[1]) & 0x00ff);
+	return 0, nil
+}
+
+
+const (
+	VoltageIdeal = 98
+	VoltageTooLow = 75
+)
+
+// GetVoltage returns current battery voltage
+func (gc *GQGMCCounter) GetVoltage() (int16, error) {
+	// Do this differently - for 9.6 return 96. And if not supported,
+	// Return -1.
+	// Public method to read voltage value of battery. The GQ GMC returns
+	// a single byte whose integer value converted to a float divided by 10
+	// equals the battery voltage. For example, 0x60 = 96 converts to 9.6 Volts.
+	// The ideal value is 9.8 volts. So practically speaking, we should not
+	// expect to see a value higher than 100. The command is get_voltage_cmd
+	// (see GQ GMC COMMANDS above). If the voltage falls below 7.5V, GQ LLC
+	// says the geiger counter cannot be expected to operate properly.
+	//func (gc *GQGMCCounter) getBatteryVoltage()
+	//uint32_t     voltsize = 1;             // one byte of returned data
+	// Issue command to get battery voltage and read returned data.
+	//communicate(get_voltage_cmd, voltage_char, voltsize);
+	// If read of returned data succeeded, convert raw data to float,
+	//int32_t  voltage_int = int16_t(voltage_char[0]);
+	//voltage = float(voltage_int) / 10.0;
+
+	return 0, nil
+}
+
+// GetHistoryData Should return history data but is unimplemented for now
+func (gc *GQGMCCounter) GetHistoryData() {
+	// It's not recommended to use this so blank for now.
+}
+
+func (gc *GQGMCCounter) TurnOnCPS() error {
+// turnOnCPS is public method to enable automatic reporting of the
+// count per second (CPS) value. First, I would say don't use this
+// command. Since the returned data has no protocol, that is, there
+// is no start/stop marker, no identification, no nothing but a
+// sequence of bytes, any other command issued while CPS is turned on
+// will take extraordinary effort not to confuse its returned data
+// with the CPS data. To handle it correctly, you would have to
+// wait for the CPS data to be returned, and then issue the command.
+// This would be most safely done by creating a new thread to
+// read the CPS and using a mutex to signal opportunity to issue a
+// separate command. The command is turn_on_cps_cmd
+// (see GQ GMC COMMANDS above). The returned data is always two
+// bytes so that samples > 255 can be reported (even though unlikely).
+//sendCmd(turn_on_cps_cmd);
+// There is no pass/fail return from GQ GMC
+}
+
+func (gc *GQGMCCounter) TurnOffCPS() error {
+//sendCmd(turn_off_cps_cmd);
+//call Clear()
+}
+
+func (gc *GQGMCCounter) getAutoCPS() (uint16, error) {
+	//uint32_t cpssize = 2;          // 2 bytes of returned data
+	//read-from-port(cps_char, cpssize);
+	// 1st byte is MSB, but note that upper two bits are reserved bits.
+	// Note that shifting and bitmasking performed in uP register, so
+	// endianess is irrevelant.
+	//cps_int |= ((uint16_t(cps_char[0]) << 8) & 0x3f00);
+	//cps_int |=  (uint16_t(cps_char[1]) & 0x00ff);
+	return 0, nil
 }
 
-// GetReading returns a reading.
-func (gc *GQGMCCounter) GetReading() (*Reading, error) {
-	return nil, nil
+func (gc *GQGMCCounter) TurnOffPower() {
+  sendCmd(turn_off_pwr_cmd);
+  // Note that power off cannot fail because the GQ GMC returns nothing.
 }