matthijskooijman / arduino-lmic

:warning: This library is deprecated, see the README for alternatives.
705 stars 651 forks source link

hal_tics() understand? #165

Closed ios198 closed 6 years ago

ios198 commented 6 years ago

I am new to LMic library. I successfully port Lmic library to Arduino Uno and tested raw.ino example. I dont really completely understand this hal_ticks() function.

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). 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.
uint32_t scaled = micros() >> US_PER_OSTICK_EXPONENT;
// Most significant byte of scaled
uint8_t msb = scaled >> 24;
// Mask pointing to the overlapping bit in msb and overflow.
const uint8_t mask = (1 << (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) & 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.
return scaled | ((uint32_t)overflow << 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 > 0 && US_PER_OSTICK_EXPONENT < 8, "Invalid 
US_PER_OSTICK_EXPONENT value");
}

*For example with the typical Arduino has a 16MHz oscillator: 1 ticks of Timer0 ~ 4(us) => is that reason US_PER_OSTICK_EXPONENT = 4? scaled= number of ticks = (micors() >> US_PER_OSTICK_EXPONENT ) = ((timer0_overflow_count << 8) + TCNT0)/4 and I dont know how to explain next parts to really get the meaning of this function.

matthijskooijman commented 6 years ago

1 ticks of Timer0 ~ 4(us) => is that reason US_PER_OSTICK_EXPONENT = 4?

Nope, an "ostick" is the time unit internally used within LMIC and must be (according to original docs) 15.5μs - 100 μs. Arduino-LMIC chooses to make it 16us, which is 2^4, hence US_PER_OSTICK_EXPONENT=4.

The complexity of this function is to deal with overflow: micros() runs up to 2^32us, which corresponds to 2^28 osticks. To prevent the return value of hal_ticks() from overflowing back to 0 when it reaches 2^28, a couple of extra bits are stored and incremented on such an overflow, so the hal_ticks() return value only correctly runs up to 2^32 before overflowing.

#ifndef OSTICKS_PER_SEC
#define OSTICKS_PER_SEC 32768 

This is just the LMIC default setting (used for the original ARM port, which uses ~30us per ostick), but on Arduino-LMIC this setting is overridden here:

https://github.com/matthijskooijman/arduino-lmic/blob/ba1265d5d2f775177cdc7c82186724e4f0bdc3a8/src/lmic/config.h#L21

ios198 commented 6 years ago

Thank you for your explanation. Before closing this issue , I just want to ask that is this library still in development? I cannot find other LoraMac library for Arduino. And do you any plan porting Semtech LoraMac-node for Arduino? I found a library form here: https://github.com/arduino-org/arduino-library-lora-node-shield?utm_source=platformio&utm_medium=piohome But it not compatible with Arduino Avr boards.

matthijskooijman commented 6 years ago

I'm still planning to work on this library, but it's not a real priority right now. I looked at LoraMac-node, but I suspect it is too bulky for a small AVR devices (I haven't tried it, though). There is also a new stack recently developed which should be lightweight, but I'm not sure if there is an AVR/Arduino port yet: https://github.com/LoRaWanMiniMouse/Mini-Mouse

hallard commented 6 years ago

Both Semtech and TTN announced at the thing conference they will open source a lorawan stack for embedded devices Hope release will come soon

matthijskooijman commented 6 years ago

I think that the stack they announced is the mini-mouse one I linked in my previous comment. The dev branch seems to contain some code, the wiki some (badly converted) documentation, but I haven't had a proper look yet.