void main(void)
{
  unsigned char x, y;

  // DEBUG / QA stats: get last reset reason:
  x = (~RCON) & 0x1f;
  if (STKPTRbits.STKFUL) x += 32;
  if (STKPTRbits.STKUNF) x += 64;

  // ...clear RCON:
  RCONbits.NOT_BOR = 1; // b0 = 1  = Brown Out Reset
  RCONbits.NOT_POR = 1; // b1 = 2  = Power On Reset
  //RCONbits.NOT_PD = 1;    // b2 = 4  = Power Down detection
  //RCONbits.NOT_TO = 1;    // b3 = 8  = watchdog TimeOut occured
  RCONbits.NOT_RI = 1; // b4 = 16 = Reset Instruction

  if (x == 3) // 3 = normal Power On
  {
    debug_crashreason = 0;
    debug_crashcnt = 0;
#ifdef OVMS_LOGGINGMODULE
    logging_initialise();
#endif
  }
  else
  {
    debug_crashreason = x | 0x80; // 0x80 = keep checkpoint until sent to server
    debug_crashcnt++;
  }

  CHECKPOINT(0x20)

  for (x = 0; x < FEATURES_MAP_PARAM; x++)
    sys_features[x] = 0; // Turn off the features

  // The top N features are persistent
  for (x = FEATURES_MAP_PARAM; x < FEATURES_MAX; x++)
  {
    sys_features[x] = atoi(par_get(PARAM_FEATURE_S + (x - FEATURES_MAP_PARAM)));
  }

  // Make sure cooldown is off
  car_coolingdown = -1;

  // Port configuration
  inputs_initialise();
  TRISB = 0xFE;

  // Timer 0 enabled, Fosc/4, 16 bit mode, prescaler 1:256
  // This gives us one tick every 51.2uS before prescale (13.1ms after)
  T0CON = 0b10000111; // @ 5Mhz => 51.2uS

  // Initialisation...
  led_initialise();
  par_initialise();
  vehicle_initialise();
  net_initialise();

  CHECKPOINT(0x21)

  // Startup sequence...
  // Holding the RED led on, pulse out the firmware version on the GREEN led
  delay100(10); // Delay 1 second
  led_set(OVMS_LED_RED, OVMS_LED_ON);
  led_set(OVMS_LED_GRN, OVMS_LED_OFF);
  led_start();
  delay100(10); // Delay 1.0 seconds
  led_set(OVMS_LED_GRN, ovms_firmware[0]);
  led_start();
  delay100(35); // Delay 3.5 seconds
  ClrWdt(); // Clear Watchdog Timer
  led_set(OVMS_LED_GRN, ovms_firmware[1]);
  led_start();
  delay100(35); // Delay 3.5 seconds
  ClrWdt(); // Clear Watchdog Timer
  led_set(OVMS_LED_GRN, ovms_firmware[2]);
  led_start();
  delay100(35); // Delay 3.5 seconds
  ClrWdt(); // Clear Watchdog Timer
  led_set(OVMS_LED_GRN, OVMS_LED_OFF);
  led_set(OVMS_LED_RED, OVMS_LED_OFF);
  led_start();
  delay100(10); // Delay 1 second
  ClrWdt(); // Clear Watchdog Timer

  // Setup ready for the main loop
  led_set(OVMS_LED_GRN, OVMS_LED_OFF);
  led_start();

#ifdef OVMS_HW_V2
  car_12vline = inputs_voltage()*10;
  car_12vline_ref = 0;
#endif

#ifdef OVMS_ACCMODULE
  acc_initialise();
#endif

  // Proceed to main loop
  y = 0; // Last TMR0H
  while (1) // Main Loop
  {
    CHECKPOINT(0x22)
    if ((vUARTIntStatus.UARTIntRxError) ||
            (vUARTIntStatus.UARTIntRxOverFlow))
      net_reset_async();

    while (!vUARTIntStatus.UARTIntRxBufferEmpty)
    {
      CHECKPOINT(0x23)
      net_poll();
    }

    CHECKPOINT(0x24)
    vehicle_idlepoll();

    ClrWdt(); // Clear Watchdog Timer

    x = TMR0L;
    if (TMR0H >= 0x4c) // Timout ~1sec (actually 996ms)
    {
      TMR0H = 0;
      TMR0L = 0; // Reset timer
      CHECKPOINT(0x25)
      net_ticker();
      CHECKPOINT(0x26)
      vehicle_ticker();
#ifdef OVMS_LOGGINGMODULE
      CHECKPOINT(0x27)
      logging_ticker();
#endif
#ifdef OVMS_ACCMODULE
      CHECKPOINT(0x28)
      acc_ticker();
#endif
    }
    else if (TMR0H != y)
    {
      if ((TMR0H % 0x04) == 0)
      {
        CHECKPOINT(0x29)
        net_ticker10th();
        CHECKPOINT(0x2A)
        vehicle_ticker10th();
        CHECKPOINT(0x2B)
      }
      y = TMR0H;
    }
  }
void main(void)
  {
  unsigned char x,y;
  char *p;

  for (x=0;x<FEATURES_MAP_PARAM;x++)
    sys_features[x]=0; // Turn off the features

  // The top N features are persistent
  for (x=FEATURES_MAP_PARAM;x<FEATURES_MAX;x++)
    {
    sys_features[x] = atoi(par_get(PARAM_FEATURE_S+(x-FEATURES_MAP_PARAM)));
    }

  // Port configuration
  inputs_initialise();
  TRISB = 0xFE;

  // Timer 0 enabled, Fosc/4, 16 bit mode, prescaler 1:256
  // This gives us one tick every 51.2uS before prescale (13.1ms after)
  T0CON = 0b10000111; // @ 5Mhz => 51.2uS

  // Initialisation...
  led_initialise();
  par_initialise();
  can_initialise();
  net_initialise();

  // Startup sequence...
  // Holding the RED led on, pulse out the firmware version on the GREEN led
  delay100(10); // Delay 1 second
  led_set(OVMS_LED_RED,OVMS_LED_ON);
  led_set(OVMS_LED_GRN,OVMS_LED_OFF);
  led_start();
  delay100(10); // Delay 1.0 seconds
  led_set(OVMS_LED_GRN, ovms_firmware[0]);
  led_start();
  delay100(35); // Delay 3.5 seconds
  ClrWdt();		// Clear Watchdog Timer
  led_set(OVMS_LED_GRN, ovms_firmware[1]);
  led_start();
  delay100(35); // Delay 3.5 seconds
  ClrWdt();		// Clear Watchdog Timer
  led_set(OVMS_LED_GRN, ovms_firmware[2]);
  led_start();
  delay100(35); // Delay 3.5 seconds
  ClrWdt();		// Clear Watchdog Timer
  led_set(OVMS_LED_GRN, OVMS_LED_OFF);
  led_set(OVMS_LED_RED, OVMS_LED_OFF);
  led_start();
  delay100(10); // Delay 1 second
  ClrWdt();		// Clear Watchdog Timer

  // Setup ready for the main loop
  led_set(OVMS_LED_GRN,NET_LED_WAKEUP);
  led_start();

  // Proceed to main loop
  y = 0; // Last TMR0H
  while (1) // Main Loop
    {
    if((vUARTIntStatus.UARTIntRxError) ||
       (vUARTIntStatus.UARTIntRxOverFlow))
      net_reset_async();
    if (! vUARTIntStatus.UARTIntRxBufferEmpty)
      net_poll();

    can_idlepoll();

    ClrWdt();		// Clear Watchdog Timer

    x = TMR0L;
    if (TMR0H >= 0x4c) // Timout ~1sec (actually 996ms)
      {
      TMR0H = 0; TMR0L = 0; // Reset timer
      net_ticker();
      can_ticker();
      }
    else if (TMR0H != y)
      {
      if ((TMR0H % 0x04)==0)
        {
        net_ticker10th();
        can_ticker10th();
        }
      y = TMR0H;
      }
    }
  }