Ejemplo n.º 1
0
static void MENU_update(void)
{
    static const far rom char *values[] = {
        (ROMCHAR)"OFF",
        (ROMCHAR)"ON",
    };

    static const far rom char *formats[] = {
        (ROMCHAR)" STEREO     ",
        (ROMCHAR)" BASS BOOST ",
        (ROMCHAR)" RDS        ",
        (ROMCHAR)" ABOUT          "
    };

    memset(menu[0].title, ' ', 16);
    memset(menu[1].title, ' ', 16);
    memset(menu[2].title, ' ', 16);

    strcpypgm2ram(menu[0].title, formats[0]);
    strcpypgm2ram(menu[1].title, formats[1]);
    strcpypgm2ram(menu[2].title, formats[2]);
    strcpypgm2ram(menu[3].title, formats[3]);

    strcatpgm2ram(menu[0].title, values[!(mem_data->flags & RDA_FLAG_MONO)]);
    strcatpgm2ram(menu[1].title, values[(mem_data->flags & RDA_FLAG_BASS) == RDA_FLAG_BASS]);
    strcatpgm2ram(menu[2].title, values[(mem_data->flags & RDA_FLAG_RDS) == RDA_FLAG_RDS]);
}
Ejemplo n.º 2
0
void Keyboard(void) {
  static char* c = g_tx_queue;

  if (SwitchIsPressed()) {
    g_tx_queue[0] = 0;
    if (g_config_mode) {
      ++g_lgtm_strings_idx;
      if (g_lgtm_strings_idx >= NUM_LGTM_STRINGS)
        g_lgtm_strings_idx = 0;
      EEADR = 0;
      EEDATA = g_lgtm_strings_idx;
      EECON1bits.EEPGD = 0;
      EECON1bits.CFGS = 0;
      EECON1bits.WREN = 1;
      EECON2 = 0x55;
      EECON2 = 0xAA;
      EECON1bits.WR = 1;
      strcatpgm2ram(g_tx_queue, CFG_MODE_STR);
    }
    strcatpgm2ram(g_tx_queue, LGTM_STRINGS[g_lgtm_strings_idx]);
    c = g_tx_queue;
  }

  // Check if the IN endpoint is not busy, and if it isn't check if we want to
  // send keystroke data to the host.
  if (!HIDTxHandleBusy(g_usb_handle_in)) {
    memset(hid_report_in, 0, sizeof(hid_report_in));
    if (*c) {
      HIDKey key;
      key = AsciiToHid(*c);
      ++c;
      hid_report_in[0] = key.modifier;
      hid_report_in[2] = key.code;
    }
    // Send the 8 byte packet over USB to the host.
    g_usb_handle_in = HIDTxPacket(HID_EP, (BYTE*)hid_report_in, 0x08);
  }

  // Check if any data was sent from the PC to the keyboard device.  Report
  // descriptor allows
  // host to send 1 byte of data.  Bits 0-4 are LED states, bits 5-7 are unused
  // pad bits.
  // The host can potentially send this OUT report data through the HID OUT
  // endpoint (EP1 OUT),
  // or, alternatively, the host may try to send LED state information by
  // sending a
  // SET_REPORT control transfer on EP0.  See the USBHIDCBSetReportHandler()
  // function.
  if (!HIDRxHandleBusy(g_usb_handle_out)) {
    // Do something useful with the data now.  Data is in the OutBuffer[0].
    // Num Lock LED state is in Bit0.
    // if (hid_report_out[0] & 0x01)  // Make LED1 and LED2 match Num Lock
    // state.
    g_usb_handle_out = HIDRxPacket(HID_EP, (BYTE*)&hid_report_out, 1);
  }

  return;
}
void net_msg_alert(void)
  {
  char *p;

  delay100(2);
  net_msg_start();
  strcpypgm2ram(net_scratchpad,(char const rom far*)"MP-0 PA");

  switch (car_chargemode)
    {
    case 0x00:
      strcatpgm2ram(net_scratchpad,(char const rom far *)"Standard - "); // Charge Mode Standard
      break;
    case 0x01:
      strcatpgm2ram(net_scratchpad,(char const rom far *)"Storage - "); // Storage
      break;
    case 0x03:
      strcatpgm2ram(net_scratchpad,(char const rom far *)"Range - "); // Range
      break;
    case 0x04:
      strcatpgm2ram(net_scratchpad,(char const rom far *)"Performance - "); // Performance
    }
  switch (car_chargestate)
    {
    case 0x01:
      strcatpgm2ram(net_scratchpad,(char const rom far *)"Charging"); // Charge State Charging
      break;
    case 0x02:
      strcatpgm2ram(net_scratchpad,(char const rom far *)"Charging, Topping off"); // Topping off
      break;
    case 0x04:
      strcatpgm2ram(net_scratchpad,(char const rom far *)"Charging Done"); // Done
      break;
    default:
      strcatpgm2ram(net_scratchpad,(char const rom far *)"Charging Stopped"); // Stopped
    }

  strcatpgm2ram(net_scratchpad,(char const rom far *)"\rIdeal Range: "); // Ideal Range
  p = par_get(PARAM_MILESKM);
  if (*p == 'M') // Kmh or Miles
    sprintf(net_msg_scratchpad, (rom far char*)"%u mi", car_idealrange); // Miles
  else
    sprintf(net_msg_scratchpad, (rom far char*)"%u Km", (unsigned int) ((float) car_idealrange * 1.609)); // Kmh
  strcat((char*)net_scratchpad,net_msg_scratchpad);

  strcatpgm2ram(net_scratchpad,(char const rom far *)" SOC: ");
  sprintf(net_msg_scratchpad, (rom far char*)"%u%%", car_SOC); // 95%
  strcat(net_scratchpad,net_msg_scratchpad);
  net_msg_encode_puts();
  net_msg_send();
  }
void net_msg_tpms(void)
  {
  char k;
  long p;
  int b,a;

  if ((car_tpms_t[0]==0)&&(car_tpms_t[1]==0)&&
      (car_tpms_t[2]==0)&&(car_tpms_t[3]==0))
    return; // No TPMS, no report

  strcpypgm2ram(net_scratchpad,(char const rom far*)"MP-0 W");
  for (k=0;k<4;k++)
    {
    if (car_tpms_t[k]>0)
      {
      p = (long)((float)car_tpms_p[k]/0.2755);
      b = (p / 10);
      a = (p % 10);
      sprintf(net_msg_scratchpad, (rom far char*)"%d.%d,%d,",
              b,a,(int)(car_tpms_t[k]-40));
      strcat(net_scratchpad,net_msg_scratchpad);
      }
    else
      {
      strcatpgm2ram(net_scratchpad, (rom far char*)"0,0,");
      }
    }
  net_scratchpad[strlen(net_scratchpad)-1] = 0; // Remove trailing ','
  net_msg_encode_puts();
  }
void net_msg_stat(void)
  {
  char *p;

  strcpypgm2ram(net_scratchpad,(char const rom far*)"MP-0 S");
  p = par_get(PARAM_MILESKM);
  sprintf(net_msg_scratchpad,(rom far char*)"%d,%s,%d,%d,",car_SOC,p,car_linevoltage,car_chargecurrent);
  strcat(net_scratchpad,net_msg_scratchpad);
  switch (car_chargestate)
    {
    case 0x01:
      strcatpgm2ram(net_scratchpad,(char const rom far*)"charging,"); // Charge State Charging
      break;
    case 0x02:
      strcatpgm2ram(net_scratchpad,(char const rom far*)"topoff,"); // Topping off
      break;
    case 0x04:
      strcatpgm2ram(net_scratchpad,(char const rom far*)"done,"); // Done
      break;
    default:
      strcatpgm2ram(net_scratchpad,(char const rom far*)"stopped,"); // Stopped
    }
  switch (car_chargemode)
    {
    case 0x00:
      strcatpgm2ram(net_scratchpad,(char const rom far*)"standard,"); // Charge Mode Standard
      break;
    case 0x01:
      strcatpgm2ram(net_scratchpad,(char const rom far*)"storage,"); // Storage
      break;
    case 0x03:
      strcatpgm2ram(net_scratchpad,(char const rom far*)"range,"); // Range
      break;
    case 0x04:
      strcatpgm2ram(net_scratchpad,(char const rom far*)"performance,"); // Performance
    default:
      strcatpgm2ram(net_scratchpad,(char const rom far*)",");
    }
  if (*p == 'M') // Kmh or Miles
    sprintf(net_msg_scratchpad, (rom far char*)"%u,", car_idealrange);
  else
    sprintf(net_msg_scratchpad, (rom far char*)"%u,", (unsigned int) ((float) car_idealrange * 1.609));
  strcat(net_scratchpad,net_msg_scratchpad);
  if (*p == 'M') // Kmh or Miles
    sprintf(net_msg_scratchpad, (rom far char*)"%u", car_estrange);
  else
    sprintf(net_msg_scratchpad, (rom far char*)"%u", (unsigned int) ((float) car_estrange * 1.609));
  strcat(net_scratchpad,net_msg_scratchpad);
  net_msg_encode_puts();
  }
void net_msg_forward_sms(char *caller, char *SMS)
  {
  //Server not ready, stop sending
  //TODO: store this message inside buffer, resend it when server is connected
  if ((net_msg_serverok == 0)||(net_msg_sendpending)>0)
    return;

  delay100(2);
  net_msg_start();
  strcpypgm2ram(net_scratchpad,(char const rom far*)"MP-0 PA");
  strcatpgm2ram(net_scratchpad,(char const rom far*)"SMS FROM: ");
  strcat(net_scratchpad, caller);
  strcatpgm2ram(net_scratchpad,(char const rom far*)" - MSG: ");
  SMS[70]=0; // Hacky limit on the max size of an SMS forwarded
  strcat(net_scratchpad, SMS);
  net_msg_encode_puts();
  net_msg_send();
  }
// Receive a NET msg from the OVMS server
void net_msg_in(char* msg)
  {
  int k;

  if (net_msg_serverok == 0)
    {
    if (memcmppgm2ram(msg, (char const rom far*)"MP-S 0 ", 7) == 0)
      {
      net_msg_server_welcome(msg+7);
      }
    return; // otherwise ignore it
    }

  // Ok, we've got an encrypted message waiting for work.
  // The following is a nasty hack because base64decode doesn't like incoming
  // messages of length divisible by 4, and is really expecting a CRLF
  // terminated string, so we give it one...
  strcatpgm2ram(msg,(char const rom far*)"\r\n");
  k = base64decode(msg,net_scratchpad);
  RC4_crypt(&rx_crypto1, &rx_crypto2, net_scratchpad, k);
  if (memcmppgm2ram(net_scratchpad, (char const rom far*)"MP-0 ", 5) == 0)
    {
    msg = net_scratchpad+5;
    switch (*msg)
      {
      case 'A': // PING
        strcpypgm2ram(net_scratchpad,(char const rom far*)"MP-0 a");
        if (net_msg_sendpending==0)
          {
          net_msg_start();
          net_msg_encode_puts();
          net_msg_send();
          }
        break;
      case 'Z': // PEER connection
        if (msg[1] != '0')
          {
          net_apps_connected = 1;
          if (net_msg_sendpending==0)
            {
            net_msg_start();
            net_msg_stat();
            net_msg_gps();
            net_msg_tpms();
            net_msg_firmware();
            net_msg_environment();
            net_msg_send();
            }
          }
        else
          {
          net_apps_connected = 0;
          }
        break;
      }
    }
  }
void net_msg_gps(void)
  {
  strcpypgm2ram(net_scratchpad,(char const rom far*)"MP-0 L");
  format_latlon(car_latitude,net_msg_scratchpad);
  strcat(net_scratchpad,net_msg_scratchpad);
  strcatpgm2ram(net_scratchpad,(char const rom far*)",");
  format_latlon(car_longitude,net_msg_scratchpad);
  strcat(net_scratchpad,net_msg_scratchpad);
  net_msg_encode_puts();
  }
// Receive a NET msg from the OVMS server
void net_msg_in(char* msg)
  {
  int k;
  char s;

  if (net_msg_serverok == 0)
    {
    if (memcmppgm2ram(msg, (char const rom far*)"MP-S 0 ", 7) == 0)
      {
      net_msg_server_welcome(msg+7);
      net_granular_tick = 3590; // Nasty hack to force a status transmission in 10 seconds
      }
    return; // otherwise ignore it
    }

  // Ok, we've got an encrypted message waiting for work.
  // The following is a nasty hack because base64decode doesn't like incoming
  // messages of length divisible by 4, and is really expecting a CRLF
  // terminated string, so we give it one...
  CHECKPOINT(0x40)
  if (((strlen(msg)*4)/3) >= (NET_BUF_MAX-3))
    {
    // Quick exit to reset link if incoming message is too big
    net_state_enter(NET_STATE_DONETINIT);
    return;
    }
  strcatpgm2ram(msg,(char const rom far*)"\r\n");
  k = base64decode(msg,net_scratchpad);
  CHECKPOINT(0x41)
  RC4_crypt(&rx_crypto1, &rx_crypto2, net_scratchpad, k);
  if (memcmppgm2ram(net_scratchpad, (char const rom far*)"MP-0 ", 5) != 0)
    {
    net_state_enter(NET_STATE_DONETINIT);
    return;
    }
  msg = net_scratchpad+5;

  if ((*msg == 'E')&&(msg[1]=='M'))
    {
    // A paranoid-mode message from the server (or, more specifically, app)
    // The following is a nasty hack because base64decode doesn't like incoming
    // messages of length divisible by 4, and is really expecting a CRLF
    // terminated string, so we give it one...
    msg += 2; // Now pointing to the code just before encrypted paranoid message
    strcatpgm2ram(msg,(char const rom far*)"\r\n");
    k = base64decode(msg+1,net_msg_scratchpad+1);
    RC4_setup(&pm_crypto1, &pm_crypto2, pdigest, MD5_SIZE);
    for (k=0;k<1024;k++)
      {
      net_scratchpad[0] = 0;
      RC4_crypt(&pm_crypto1, &pm_crypto2, net_scratchpad, 1);
      }
    RC4_crypt(&pm_crypto1, &pm_crypto2, net_msg_scratchpad+1, k);
    net_msg_scratchpad[0] = *msg; // The code
    // The message is now out of paranoid mode...
    msg = net_msg_scratchpad;
    }

  CHECKPOINT(0x42)
  switch (*msg)
    {
    case 'A': // PING
      strcpypgm2ram(net_scratchpad,(char const rom far*)"MP-0 a");
      if (net_msg_sendpending==0)
        {
        net_msg_start();
        net_msg_encode_puts();
        net_msg_send();
        }
      break;
    case 'Z': // PEER connection
      if (msg[1] != '0')
        {
        net_apps_connected = 1;
        if (net_msg_sendpending==0)
          {
          net_msg_start();
          net_msgp_stat(0);
          net_msgp_gps(0);
          net_msgp_tpms(0);
          net_msgp_firmware(0);
          net_msgp_environment(0);
          net_msg_send();
          }
        }
      else
        {
        net_apps_connected = 0;
        }
      break;
    case 'h': // Historical data acknowledgement
#ifdef OVMS_LOGGINGMODULE
      logging_ack(atoi(msg+1));
#endif // #ifdef OVMS_LOGGINGMODULE
      break;
    case 'C': // COMMAND
      net_msg_cmd_in(msg+1);
      if (net_msg_sendpending==0) net_msg_cmd_do();
      break;
    }
  }
Ejemplo n.º 10
0
/*****************************************************************************
  Function:
    void PingDemo(void)

  Summary:
    Demonstrates use of the ICMP (Ping) client.

  Description:
    This function implements a simple ICMP client.  The function is called
    periodically by the stack, and it checks if BUTTON0 has been pressed.
    If the button is pressed, the function sends an ICMP Echo Request (Ping)
    to a Microchip web server.  The round trip time is displayed on the UART
    when the response is received.

    This function can be used as a model for applications requiring Ping
    capabilities to check if a host is reachable.

  Precondition:
    TCP is initialized.

  Parameters:
    None

  Returns:
    None
  ***************************************************************************/
void PingDemo(void)
{
    static enum
    {
        SM_HOME = 0,
        SM_GET_ICMP_RESPONSE
    } PingState = SM_HOME;
    static uint32_t Timer;
    int32_t ret;

    switch(PingState)
    {
        case SM_HOME:
            // Send a ping request out if the user pushes BUTTON0 (right-most one)
            if(BUTTON0_IO == 0u)
            {
                // Don't ping flood: wait at least 1 second between ping requests
                if(TickGet() - Timer > 1ul*TICK_SECOND)
                {
                    // Obtain ownership of the ICMP module
                    if(!ICMPBeginUsage())
                        break;

                    // Update anti-ping flood timer
                    Timer = TickGet();

                    // Send ICMP echo request
                    #if defined(STACK_USE_DNS)
                        ICMPSendPingToHostROM((ROM uint8_t*)HOST_TO_PING);
                    #else
                        ICMPSendPing(AppConfig.MyGateway.Val);
                    #endif
                    PingState = SM_GET_ICMP_RESPONSE;
                }
            }
            break;

        case SM_GET_ICMP_RESPONSE:
            // Get the status of the ICMP module
            ret = ICMPGetReply();
            if(ret == -2)
            {
                // Do nothing: still waiting for echo
                break;
            }
            else if(ret == -1)
            {
                // Request timed out
                #if defined(USE_LCD)
                memcpypgm2ram((void*)&LCDText[16], (ROM void *)"Ping timed out", 15);
                LCDUpdate();
                #endif
                PingState = SM_HOME;
            }
            else if(ret == -3)
            {
                // DNS address not resolvable
                #if defined(USE_LCD)
                memcpypgm2ram((void*)&LCDText[16], (ROM void *)"Can't resolve IP", 16);
                LCDUpdate();
                #endif
                PingState = SM_HOME;
            }
            else
            {
                // Echo received.  Time elapsed is stored in ret (Tick units).
                #if defined(USE_LCD)
                memcpypgm2ram((void*)&LCDText[16], (ROM void *)"Reply: ", 7);
                uitoa((uint16_t)TickConvertToMilliseconds((uint32_t)ret), &LCDText[16+7]);
                strcatpgm2ram((char*)&LCDText[16+7], "ms");
                LCDUpdate();
                #endif
                PingState = SM_HOME;
            }

            // Finished with the ICMP module, release it so other apps can begin using it
            ICMPEndUsage();
            break;
    }
}
Ejemplo n.º 11
0
Archivo: EOL.c Proyecto: oden65/xPL_PIC
Zone_States CheckEOL (int ZoneID, WORD* ADval) {
	
	char AN0String[7];
	char DebugTemp[7];
	int PlexerDevice, BinaryValue;
	
	// Disable all analogue multiplexer
	PLEXERA_S_IO = 1; // High = disabled		
	PLEXERB_S_IO = 1;
	PLEXERC_S_IO = 1;
	
	// Select the analogue multiplexer
	PlexerDevice = ZoneID / 8;
	BinaryValue = ZoneID - ((ZoneID / 8) * 8); // The value can now be expressed as a 3 bit value
	
	
	if (PlexerDevice == 0) {
		
		PLEXERA_S_IO = 0; //enable this device
		PLEXERA_2_IO = ((BinaryValue / 4 > 0)?TRUE:FALSE);
		BinaryValue -= (BinaryValue / 4) * 4;		
		PLEXERA_1_IO = ((BinaryValue / 2 > 0)?TRUE:FALSE);
		BinaryValue -= (BinaryValue / 2) * 2;		
		PLEXERA_0_IO = ((BinaryValue > 0)?TRUE:FALSE);
		
	} // PlexerDevice ==0
	
	
	else if (PlexerDevice == 1) {
		PLEXERB_S_IO = 0; //enable this device
		PLEXERB_2_IO = BinaryValue / 4;
		BinaryValue -= (BinaryValue / 4) * 4;
		PLEXERB_1_IO = BinaryValue / 2;
		BinaryValue -= (BinaryValue / 2) * 2;
		PLEXERB_0_IO = BinaryValue;
	} // PlexerDevice == 1
	
	else if (PlexerDevice == 2) {
		PLEXERC_S_IO = 0; //enable this device
		PLEXERC_2_IO = BinaryValue / 4;
		BinaryValue -= (BinaryValue / 4) * 4;
		PLEXERC_1_IO = BinaryValue / 2;
		BinaryValue -= (BinaryValue / 2) * 2;
		PLEXERC_0_IO = BinaryValue;
	} // PlexerDevice == 2
	
	else {
#if defined(DEBUG_UART)
		putrsUART((ROM char*)" !!! CheckEOL is out of range !!!!! ");
#endif
		*ADval = 0;
		return StateNormal;
	}
	
	
	
	//60 ns delay is required for the Multiplexer to swith analogue channels
	//Nop();Nop();Nop();Nop();Nop();
	
	// Select A/D channel AN4
	ADCON0 = 0b00010000;	// ADON = On(1), GO/DONE = Idle (0), AN4 selected (0100), not used (0), calibration off (0)
	ADCON0bits.ADON = 1;
    ADCON0bits.GO = 1;
	
    // Wait until A/D conversion is done
    while(ADCON0bits.GO);
	
    // Convert 10-bit value into ASCII string
    *ADval = (WORD)ADRES;
    uitoa(*ADval, AN0String);
 	
	if (ZoneID == 1) {
		memset(LCDText, '\0', 32);
		if (strlen(AN0String) < (unsigned int)4 ) strcatpgm2ram(AN0String, (rom char *) " ");
		if (strlen(AN0String) < (unsigned int)4 ) strcatpgm2ram(AN0String, (rom char *) " ");
		if (strlen(AN0String) < (unsigned int)4 ) strcatpgm2ram(AN0String, (rom char *) " ");
		
		strcat(LCDText, AN0String);
		strcatpgm2ram(LCDText, (rom char *) "->");
	}	
	
	if ( (*ADval >= (WORD)(EOLNORMAL - EOLTOLERANCE)) && (*ADval <= (WORD)(EOLNORMAL + EOLTOLERANCE))) {
		if (ZoneID == 1) {
			strcatpgm2ram(LCDText, (rom char *) "Normal");
			LCDUpdate();
		}	
		// Need to consider if the zone is Normaly Open or Normaly Closed
		if (ZoneConfig[ZoneID].IsNO == FALSE)
			return StateNormal;
		else
			return StateTrigger;
	}
	
	else if ( (*ADval >= (WORD)(EOLTRIGGER - EOLTOLERANCE)) && (*ADval <= (WORD)(EOLTRIGGER + EOLTOLERANCE))) {
		if (ZoneID == 1) {	
			strcatpgm2ram(LCDText, (rom char *) "Trigger");
			LCDUpdate();
		}	
		// Need to consider if the zone is Normaly Open or Normaly Closed
		if (ZoneConfig[ZoneID].IsNO == FALSE)
			return StateTrigger;
		else
			return StateNormal;

	}
	
	else {
		
		if (ZoneID == 1) {
			strcatpgm2ram(LCDText, (rom char *) "Tamper");
			LCDUpdate();
		}	
		return StateTamper;
	}	
	
	
    
	
} // CheckEOL
Ejemplo n.º 12
0
void main(void)
{
  static nabto_main_setup* nms;
  static char versionString[NABTO_DEVICE_VERSION_MAX_SIZE];
  static char idString[NABTO_DEVICE_NAME_MAX_SIZE];
#if NABTO_ENABLE_UCRYPTO
  static const far rom uint8_t dummySharedSecret[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  static const far rom uint8_t* sharedSecret;
#endif

  // <editor-fold desc="Load information from bootloader and application data areas.">

  // Clear the global TCP/IP data structure and load it with the boards unique preprogrammed MAC address.
  memset((void*) &AppConfig, 0x00, sizeof (AppConfig));
  memcpypgm2ram(&AppConfig.MyMACAddr, (const __ROM uint8_t*) bootloaderData.version1.mac, 6);

  if(bootloaderData.base.bootloaderDataVersion == 1)
  {
    strcpypgm2ram(idString, (const far rom char*) bootloaderData.version1.serialNumber);
    strcatpgm2ram(idString, ".nabduino.net");

#if NABTO_ENABLE_UCRYPTO
    //        sharedSecret = applicationData.sharedSecret; // the old pre-bootloader-version-2 way of storing the shared secret - obsolete!
#endif
  }
  else if(bootloaderData.base.bootloaderDataVersion == 2)
  {
    hardwareVersion = (uint8_t) bootloaderData.version2.hardwareVersionMajor;
    hardwareVersion <<= 8;
    hardwareVersion |= (uint8_t) bootloaderData.version2.hardwareVersionMinor;

    if(hardwareVersion == 0x0004)
    {
      hardwareVersionIndex = 0; // first version of the board that was released.
    }
    else if(hardwareVersion == 0x0102)
    {
      hardwareVersionIndex = 1; // second version of the board that was released (yes we jumped from 0.4 beta to 1.2).
    }
    else if(hardwareVersion == 0x0103)
    {
      hardwareVersionIndex = 2; // third version of the board
    }

    strcpypgm2ram(idString, (const far rom char*) bootloaderData.version2.deviceId);
    strcatpgm2ram(idString, (const far rom char*) bootloaderData.version2.productDomain);

#if NABTO_ENABLE_UCRYPTO
    sharedSecret = bootloaderData.version2.sharedSecret;
#endif
  }
  else
  { // unsupported version so it's probably safe to assume that bootloader data has been wiped - please fill in the appropriate values for your Nabduino board
    hardwareVersionIndex = 0; // hardware version 0.4 = 0, v1.2 = 1, v1.3 = 2

    AppConfig.MyMACAddr.v[0] = 0xBC; // Nabto owned MAC OUI is BC:A4:E1
    AppConfig.MyMACAddr.v[1] = 0xA4;
    AppConfig.MyMACAddr.v[2] = 0xE1;
    AppConfig.MyMACAddr.v[3] = 0x00;
    AppConfig.MyMACAddr.v[4] = 0x00;
    AppConfig.MyMACAddr.v[5] = 0x00; // If using more than one Nabduino on the same network make this byte unique for each board

    strcpypgm2ram(idString, "XXX"); // replace XXX with the id of the Nabduino board
    strcatpgm2ram(idString, ".nabduino.net");

#if NABTO_ENABLE_UCRYPTO
    sharedSecret = dummySharedSecret;
#endif
  }

  // </editor-fold>

  // Initialize IOs etc. taking into account the hardware version.
  hal_initialize();

  // Initialize the platform (timing, TCP/IP stack, DHCP and some PIC18 specific stuff)
  platform_initialize();

  network_initialize();

  nms = unabto_init_context();

  nms->id = (const char*) idString;

  // build version string: <application SVN version>/<bootloader SVN version>/<hardware major version>.<hardware minor version>
  itoa(RELEASE_MINOR, versionString);
  strcatpgm2ram(versionString + strlen(versionString), "/");
  itoa(bootloaderData.base.buildVersion, versionString + strlen(versionString));
  strcatpgm2ram(versionString + strlen(versionString), "/");
  itoa(hardwareVersion >> 8, versionString + strlen(versionString));
  strcatpgm2ram(versionString + strlen(versionString), ".");
  itoa(hardwareVersion & 0xff, versionString + strlen(versionString));
  nms->version = (const char*) versionString;

#if NABTO_ENABLE_UCRYPTO
  memcpypgm2ram(nms->presharedKey, (const __ROM void*) sharedSecret, 16);
  nms->secureAttach = true;
  nms->secureData = true;
  nms->cryptoSuite = CRYPT_W_AES_CBC_HMAC_SHA256;
#endif

  setup((char**) &nms->url);

  unabto_init();

  while(1)
  {
    hal_tick();
    platform_tick();
    network_tick();
    unabto_tick();
    loop();
  }
}