title: 65535 cnt value on TTN network
body: <p>I'm trying to run Lmic library build for arduino (<a href="https://github.com/matthijskooijman/arduino-lmic" rel="nofollow noreferrer">https://github.com/matthijskooijman/arduino-lmic</a>) to work with my Renesas Synergy SK-S7G2 board using e2 studio.
  I have altered the hal.cpp file and now the code runs perfectly and I can see the up-link message on the TTN network, The problem that I am facing is that my frame is somehow changing between aes encryption (my guess) because I have checked it before encryption and it shows the <code>LMIC.frame[6]</code> and
  <code>LMIC.frame[7]</code> values to be <code>0x00</code> but for some reason what I am receiving on the TTN network is <code>0xFF</code>. and because of this the cnt on TTN shows <code>65535</code> as the first count.</p>
  
  <p>The library has 2 aes methods which can be used and I have tried both but they give me the same result.</p>
  
  <p>The reasons I have come up with so far is:</p>
  
  <ol>
  <li>32 bit arm m4 processor may be the cause, as the library was intended for 8 bit arduino (but library also has a 32bit processor version for aes and I have tried that as well but got same result)</li>
  <li>My <code>hal_ticks()</code> function is still not doing what it is supposed to do.</li>
  </ol>
  
  <p>I would love an input from anyone, below you can see the console output on e2 studio and the physical payload received on the TTN network. I am also attaching the hal.c file that I have made.</p>
  
  <p>Thank you in advance</p>
  
  <p>physical payload received on TTN</p>
  
  <blockquote>
    <p>406511012680 FFFF 0171F9EF1810C3B61F4D4EDE940844A945CE</p>
  </blockquote>
  
  <p>console messages while running on e2 studio</p>
  
  <pre><code>Starting..
  Time: 0
  RXMODE_RSSI
  5824: engineUpdate, opmode=0x808
  7349: TXMODE, freq=868100000, len=26, SF=7, BW=125, CR=4/5, IH=0
  Packet queued
  42111: RXMODE_SINGLE, freq=868100000, SF=7, BW=125, CR=4/5, IH=0
  73505: RXMODE_SINGLE, freq=869525000, SF=9, BW=125, CR=4/5, IH=0
  75435Event
  EV_TXCOMPLETE (includes waiting for RX windows)
  79028: engineUpdate, opmode=0x900
  </code></pre>
  
  <p>hal.c file</p>
  
  <pre><code>/*
   * hal.c
   *
   *  Created on: Jul 4, 2019
   *      Author: areeb
   */
  
  
  /*******************************************************************************
   * Copyright (c) 2015 Matthijs Kooijman
   * All rights reserved. This program and the accompanying materials
   * are made available under the terms of the Eclipse Public License v1.0
   * which accompanies this distribution, and is available at
   * http://www.eclipse.org/legal/epl-v10.html
   *
   * This the HAL to run LMIC on top of the Arduino environment.
   *******************************************************************************/
  
  
  #include &lt;hal/hal.h&gt;
  #include "hal_data.h"
  #include &lt;stdio.h&gt;
  #include "../lmic/lmic.h"
  
  ssp_err_t err;
  u4_t t ;
  unsigned int ticks=0, fg=0;
  
  u2_t  cnt=0 ;
  
  uint32_t scaled = 0, ch=0;
  
  static volatile bool spi_done = false;
  static bool dio_states[3] = {0};
  
  
  
  void spi_callback(spi_callback_args_t *p_args)
  {
      SSP_PARAMETER_NOT_USED(p_args);
      spi_done= true;
  }
  
  void timer0_callback(timer_callback_args_t *p_args)
  {
      SSP_PARAMETER_NOT_USED(p_args);
      ticks++;
  
  
  }
  
  void irq_callback(external_irq_callback_args_t *p_args)
  {
      if(p_args-&gt;channel == 1)
      {
  
          dio_states[0]=1;
          radio_irq_handler(0);
          dio_states[0]=0;
  
      }
      else if(p_args-&gt;channel == 2)
      {
  
          dio_states[1]=1;
          radio_irq_handler(1);
          dio_states[0]=0;
      }
      else if(p_args-&gt;channel == 14)
      {
  
          dio_states[2]=1;
          radio_irq_handler(2);
      }
      else
      {
          ;
      }
  //    if(p_args-&gt;channel == 14)
  //    {
  //        radio_irq_handler(2);
  //    }
  
  }
  
  
  
  // -----------------------------------------------------------------------------
  // I/O
  
  //#define nss (IOPORT_PORT_04_PIN_13)
  //
  //#define rst (IOPORT_PORT_05_PIN_11)
  
  
  u1_t transmit[1]={0},ccc=0;
  u1_t recv[1]={0};
  
  
  
  static void hal_io_init () {
  
  //    g_ioport.p_api-&gt;pinDirectionSet(lmic_pins.nss, IOPORT_DIRECTION_OUTPUT);
  //    g_ioport.p_api-&gt;pinCfg(lmic_pins.dio[0], IOPORT_DIRECTION_INPUT|IOPORT_CFG_EVENT_FALLING_EDGE);
  //    g_ioport.p_api-&gt;pinDirectionSet(lmic_pins.dio[0], IOPORT_DIRECTION_INPUT);
  //    g_ioport.p_api-&gt;pinCfg(lmic_pins.dio[1], IOPORT_DIRECTION_INPUT|IOPORT_CFG_EVENT_FALLING_EDGE);
  //    g_ioport.p_api-&gt;pinDirectionSet(lmic_pins.dio[1], IOPORT_DIRECTION_INPUT);
  //    g_ioport.p_api-&gt;pinCfg(lmic_pins.dio[2], IOPORT_DIRECTION_INPUT|IOPORT_CFG_EVENT_FALLING_EDGE);
  //    g_ioport.p_api-&gt;pinDirectionSet(lmic_pins.dio[2], IOPORT_DIRECTION_INPUT);
  
  
  }
  
  // val == 1  =&gt; tx 1
  void hal_pin_rxtx (u1_t val) {
  
  }
  
  // set radio RST pin to given value (or keep floating!)
  void hal_pin_rst (u1_t val) {
  g_ioport.p_api-&gt;init(g_ioport.p_cfg);
      if(val == 0 || val == 1)
      {
          g_ioport.p_api-&gt;pinCfg(lmic_pins.rst, IOPORT_DIRECTION_OUTPUT);
          g_ioport.p_api-&gt;pinDirectionSet(lmic_pins.rst, IOPORT_DIRECTION_OUTPUT);
              if(val == 0)
                  g_ioport.p_api-&gt;pinWrite(lmic_pins.rst,IOPORT_LEVEL_LOW);
              else if (val == 1)
                  g_ioport.p_api-&gt;pinWrite(lmic_pins.rst,IOPORT_LEVEL_HIGH);
      }
      else
      {
          g_ioport.p_api-&gt;pinCfg(lmic_pins.rst, IOPORT_DIRECTION_INPUT);
          g_ioport.p_api-&gt;pinDirectionSet(lmic_pins.rst, IOPORT_DIRECTION_INPUT);
      }
  
  
  }
  
  
  ioport_level_t readpin;
  u1_t rd=0;
  
  //static void hal_io_check() {
  //
  //    uint8_t i;
  //        for (i = 0; i &lt; NUM_DIO; ++i) {
  //            if (lmic_pins.dio[i] == 0xff)
  //                continue;
  //            g_ioport.p_api-&gt;pinRead(lmic_pins.dio[i], &amp;readpin);
  //            if(readpin == IOPORT_LEVEL_HIGH)
  //                rd = 1;
  //            else
  //                rd = 0;
  //
  //            if (dio_states[i] != readpin) {
  //                dio_states[i] = !dio_states[i];
  //            if (dio_states[i])
  //                    radio_irq_handler(i);
  //            }
  //        }
  //
  //
  //}
   void hal_io_check() {
      uint8_t i;
  //    for (i = 0; i &lt; 3; ++i) {
  //        if (lmic_pins.dio[i] == 0xff)
  //            continue;
  //
  //        if (dio_states[i] != 0) {
  //            dio_states[i] = !dio_states[i];
  //            if (dio_states[i])
  //                radio_irq_handler(i);
  //        }
  //    }
  //    radio_irq_handler(0);
  }
  
  // -----------------------------------------------------------------------------
  // SPI
  
  //static const SPISettings settings(10E6, MSBFIRST, SPI_MODE0);
  
  static void hal_spi_init () {
     err =  g_spi0.p_api-&gt;open(g_spi0.p_ctrl,g_spi0.p_cfg);
  
  
  
     err = g_timer0.p_api-&gt;open(g_timer0.p_ctrl,g_timer0.p_cfg);
     err = g_timer0.p_api-&gt;start(g_timer0.p_ctrl);
  
     g_external_irq0.p_api-&gt;open(g_external_irq0.p_ctrl,g_external_irq0.p_cfg);
    g_external_irq0.p_api-&gt;enable(g_external_irq0.p_ctrl);
    g_external_irq0.p_api-&gt;triggerSet(g_external_irq0.p_ctrl, EXTERNAL_IRQ_TRIG_BOTH_EDGE);
  
     g_external_irq1.p_api-&gt;open(g_external_irq1.p_ctrl,g_external_irq1.p_cfg);
     g_external_irq1.p_api-&gt;enable(g_external_irq1.p_ctrl);
     g_external_irq1.p_api-&gt;triggerSet(g_external_irq1.p_ctrl, EXTERNAL_IRQ_TRIG_BOTH_EDGE);
  
     g_external_irq2.p_api-&gt;open(g_external_irq2.p_ctrl,g_external_irq2.p_cfg);
     g_external_irq2.p_api-&gt;enable(g_external_irq2.p_ctrl);
     g_external_irq2.p_api-&gt;triggerSet(g_external_irq2.p_ctrl, EXTERNAL_IRQ_TRIG_BOTH_EDGE);
  
  
  }
  
  void hal_pin_nss (u1_t val) {
      g_ioport.p_api-&gt;pinDirectionSet(lmic_pins.nss, IOPORT_DIRECTION_OUTPUT);
      if(val == 0)
          g_ioport.p_api-&gt;pinWrite(lmic_pins.nss,IOPORT_LEVEL_LOW);
      else if(val == 1)
          g_ioport.p_api-&gt;pinWrite(lmic_pins.nss,IOPORT_LEVEL_HIGH);
  
  }
  
  // perform SPI transaction with radio
  u1_t hal_spi (u1_t out) {
      if((out &amp; 0x80) == 0x80)
      {
          uint8_t temp[1] = {out};
          g_spi0.p_api-&gt;write(g_spi0.p_ctrl, (const void*)temp,1,SPI_BIT_WIDTH_8_BITS);
          while(false == spi_done)
          {
            ;
          }
          spi_done = false;
          return 0;
      }
      else if((out &gt; 0x00) &amp;&amp; (out &amp; 0x80) != 0x80)
      {
          ccc = out;
          uint8_t temp[1] = {out};
          g_spi0.p_api-&gt;write(g_spi0.p_ctrl, (const void*)temp,1,SPI_BIT_WIDTH_8_BITS);
          while(false == spi_done)
          {
  ;
          }
          spi_done = false;
      }
      else if(out == 0x00)
      {
          g_spi0.p_api-&gt;read(g_spi0.p_ctrl,  recv, sizeof(recv), SPI_BIT_WIDTH_8_BITS);
          while(false == spi_done)
          {
              ;
          }
          spi_done = false;
          return recv[0];
      }
  
      return recv[0];
  }
  // -----------------------------------------------------------------------------
  // TIME
  
  static void hal_time_init () {
      // Nothing to do
  }
  
  u4_t hal_ticks () {
      // Because micros() is scaled down in this function, micros() will
      // overflow before the tick timer should, causing the tick timer to
      // miss a significant part of its values if not corrected. To fix
      // this, the "overflow" serves as an overflow area for the micros()
      // counter. It consists of three parts:
      //  - The US_PER_OSTICK upper bits are effectively an extension for
      //    the micros() counter and are added to the result of this
      //    function.
      //  - The next bit overlaps with the most significant bit of
      //    micros(). This is used to detect micros() overflows.
      //  - The remaining bits are always zero.
      //
      // By comparing the overlapping bit with the corresponding bit in
      // the micros() return value, overflows can be detected and the
      // upper bits are incremented. This is done using some clever
      // bitwise operations, to remove the need for comparisons and a
      // jumps, which should result in efficient code. By avoiding shifts
      // other than by multiples of 8 as much as possible, this is also
      // efficient on AVR (which only has 1-bit shifts).
  //    g_timer0.p_api-&gt;stop(g_timer0.p_ctrl);
  //    static uint8_t overflow = 0;
  
      // Scaled down timestamp. The top US_PER_OSTICK_EXPONENT bits are 0,
      // the others will be the lower bits of our return value.
  //    u4_t t = ticks;
  //    g_timer0.p_api-&gt;counterGet(g_timer0.p_ctrl, &amp;cnt);
  //    cnt = 65535-cnt;
  //    if( (cnt &gt; 65000) &amp;&amp; (cnt &lt; 65535 ) )
  //    {
  //        g_timer0.p_api-&gt;reset(g_timer0.p_ctrl);
  //        cnt=0;
  //        t++;
  //    }
  //    scaled = ticks &gt;&gt; US_PER_OSTICK_EXPONENT; // 625
      // Most significant byte of scaled
  //    uint8_t msb = scaled &gt;&gt; 24;
      // Mask pointing to the overlapping bit in msb and overflow.
  //    const uint8_t mask = (1 &lt;&lt; (7 - US_PER_OSTICK_EXPONENT));
      // Update overflow. If the overlapping bit is different
      // between overflow and msb, it is added to the stored value,
      // so the overlapping bit becomes equal again and, if it changed
      // from 1 to 0, the upper bits are incremented.
  //    overflow += (msb ^ overflow) &amp; mask;
  
      // Return the scaled value with the upper bits of stored added. The
      // overlapping bit will be equal and the lower bits will be 0, so
      // bitwise or is a no-op for them.
  //    g_timer0.p_api-&gt;start(g_timer0.p_ctrl);
  
  //    return scaled | ((uint32_t)overflow &lt;&lt; 24);
  
      // 0 leads to correct, but overly complex code (it could just return
      // micros() unmodified), 8 leaves no room for the overlapping bit.
  //    static_assert(US_PER_OSTICK_EXPONENT &gt; 0 &amp;&amp; US_PER_OSTICK_EXPONENT &lt; 8, "Invalid US_PER_OSTICK_EXPONENT value");
  
  
      t = ticks;
  //
  ////    hal_disableIRQs();
  ///
      g_timer0.p_api-&gt;counterGet(g_timer0.p_ctrl, &amp;cnt);
      if(cnt != 0 )
          cnt = 65535 - cnt;
  //    if( (cnt &lt; 500) )
  //    {
  //        g_timer0.p_api-&gt;reset(g_timer0.p_ctrl);
  //        cnt=0;
  //        t++;
  //    }
  //    hal_enableIRQs();
  
      return ((t&lt;&lt;16)|cnt);
  
  }
  
  // Returns the number of ticks until time. Negative values indicate that
  // time has already passed.
  static s4_t delta_time(u4_t time) {
      u4_t t = hal_ticks();
      s4_t d = time - t;
      if( d&lt;=0 ) return 0;    // in the past
      if( (d&gt;&gt;16)!=0 ) return 0xFFFF; // far ahead
      return (u2_t)d;
  }
  
  void hal_waitUntil (u4_t time) {
      while( delta_time(time) != 0 );
  }
  //    s4_t delta = delta_time(time);
  //    // From delayMicroseconds docs: Currently, the largest value that
  //    // will produce an accurate delay is 16383.
  //    while (delta &gt; (16000 / US_PER_OSTICK)) {
  //        R_BSP_SoftwareDelay(16, BSP_DELAY_UNITS_MILLISECONDS);
  //        delta -= (16000 / US_PER_OSTICK);
  //    }
  //    if (delta &gt; 0)
  //        R_BSP_SoftwareDelay((delta * US_PER_OSTICK), BSP_DELAY_UNITS_MICROSECONDS);
  ////        delayMicroseconds(delta * US_PER_OSTICK);
  //}
  
  // check and rewind for target time
  u1_t hal_checkTimer (u4_t time) {
      // No need to schedule wakeup, since we're not sleeping
      return delta_time(time) &lt;= 0;
  }
  
  static uint8_t irqlevel = 0;
  
  void hal_disableIRQs () {
  
  //    __disable_irq();
  //    g_timer0.p_api-&gt;close(g_timer0.p_ctrl);
  //    g_external_irq1.p_api-&gt;disable(g_external_irq1.p_ctrl);
  //    g_external_irq2.p_api-&gt;disable(g_external_irq2.p_ctrl);
      irqlevel++;
  }
  
  void hal_enableIRQs () {
  
      if(--irqlevel == 0) {
  //        __enable_irq();
  //        g_timer0.p_api-&gt;open(g_timer0.p_ctrl,g_timer0.p_cfg);
  //        g_external_irq1.p_api-&gt;enable(g_external_irq1.p_ctrl);
  //        g_external_irq2.p_api-&gt;enable(g_external_irq2.p_ctrl);
  
              // Instead of using proper interrupts (which are a bit tricky
              // and/or not available on all pins on AVR), just poll the pin
              // values. Since os_runloop disables and re-enables interrupts,
              // putting this here makes sure we check at least once every
              // loop.
              //
              // As an additional bonus, this prevents the can of worms that
              // we would otherwise get for running SPI transfers inside ISRs
              hal_io_check();
          }
      hal_io_check();
  
   }
  
  void hal_sleep () {
      // Not implemented
  }
  
  // -----------------------------------------------------------------------------
  
  #if defined(LMIC_PRINTF_TO)
  static int uart_putchar (char c, FILE *)
  {
      LMIC_PRINTF_TO.write(c) ;
      return 0 ;
  }
  
  void hal_printf_init() {
      // create a FILE structure to reference our UART output function
      static FILE uartout;
      memset(&amp;uartout, 0, sizeof(uartout));
  
      // fill in the UART file descriptor with pointer to writer.
      fdev_setup_stream (&amp;uartout, uart_putchar, NULL, _FDEV_SETUP_WRITE);
  
      // The uart is the standard output device STDOUT.
      stdout = &amp;uartout ;
  }
  #endif // defined(LMIC_PRINTF_TO)
  
  void hal_init () {
      // configure radio I/O and interrupt handler
      hal_io_init();
      // configure radio SPI
      hal_spi_init();
      // configure timer and interrupt handler
      hal_time_init();
  
  #if defined(LMIC_PRINTF_TO)
      // printf support
      hal_printf_init();
  #endif
  }
  
  void hal_failed (const char *file, u2_t line) {
  
  }
  </code></pre>