// Copyright (c) Microsoft Corporation. // Licensed under the MIT license. #ifndef JD_UTIL_H #define JD_UTIL_H #include "jd_physical.h" #include uint64_t jd_device_id(void); uint32_t jd_random_around(uint32_t v); uint32_t jd_random(void); void jd_seed_random(uint32_t s); uint32_t jd_hash_fnv1a(const void *data, unsigned len); // CRC-16-CCITT polynomial 0x1021 uint16_t jd_crc16(const void *data, uint32_t size); // CRC-32 ISO 3309 polynomial 0x04C11DB7 uint32_t jd_crc32(const void *data, uint32_t size); // for SD card commands; includes stop bit uint8_t jd_sd_crc7(const void *data, uint32_t size); // for SD card data uint16_t jd_sd_crc16(const void *data, uint32_t size); int jd_shift_frame(jd_frame_t *frame); void jd_reset_frame(jd_frame_t *frame); void jd_pkt_set_broadcast(jd_packet_t *pkt, uint32_t service_class); void *jd_push_in_frame(jd_frame_t *frame, unsigned service_num, unsigned service_cmd, unsigned service_size); // jd_should_sample() will try to keep the period sampling rate, when delayed bool jd_should_sample(uint32_t *sample, uint32_t period); // jd_should_sample_delay() will wait at least `period` until next sampling bool jd_should_sample_delay(uint32_t *sample, uint32_t period); // approx. a <= b modulo overflows // checks if time from a to b is at most 0x7fff_ffff static inline bool is_before(uint32_t a, uint32_t b) { return ((b - a) >> 31) == 0; } // check if given timestamp is already in the past, regardless of overflows on 'now' // the moment has to be no more than ~2100 seconds in the past static inline bool in_past(uint32_t moment) { extern uint32_t now; return is_before(moment, now); } static inline bool in_future(uint32_t moment) { extern uint32_t now; return is_before(now, moment); } #if JD_MS_TIMER // this works up to around 24 days static inline bool in_past_ms(uint32_t moment) { extern uint32_t now_ms; return is_before(moment, now_ms); } static inline bool in_future_ms(uint32_t moment) { extern uint32_t now_ms; return is_before(now_ms, moment); } bool jd_should_sample_ms(uint32_t *sample, uint32_t period); #endif // sizeof(dst) == len*2 + 1 void jd_to_hex(char *dst, const void *src, size_t len); // sizeof(dst) >= strlen(dst)/2; returns length of dst int jd_from_hex(void *dst, const char *src); #if JD_ADVANCED_STRING // buf is 64 bytes long void jd_print_double(char *buf, double d, int numdigits); int jd_vsprintf_ext(char *dst, unsigned dstsize, const char *format, unsigned *ulen, va_list ap); #endif // These allocate the resulting string // often used with custom %-s format which will free them #if JD_FREE_SUPPORTED char *jd_vsprintf_a(const char *format, va_list ap); __attribute__((format(printf, 1, 2))) char *jd_sprintf_a(const char *format, ...); char *jd_to_hex_a(const void *src, size_t len); char *jd_device_short_id_a(uint64_t long_id); void *jd_from_hex_a(const char *src, unsigned *size); char *jd_strdup(const char *s); char *jd_concat_many(const char **parts); char *jd_concat2(const char *a, const char *b); char *jd_concat3(const char *a, const char *b, const char *c); char *jd_urlencode(const char *src); jd_frame_t *jd_dup_frame(const jd_frame_t *frame); void *jd_memdup(const void *src, unsigned size); bool jd_ends_with(const char *s, const char *suff); bool jd_starts_with(const char *s, const char *pref); #endif #if JD_VERBOSE_ASSERT __attribute__((noreturn)) void jd_assert_fail(const char *expr, const char *file, unsigned line, const char *funname); __attribute__((noreturn)) void jd_panic_core(const char *file, unsigned line, const char *funname); #else #define jd_assert_fail(...) hw_panic() #define jd_panic_core(...) hw_panic() #endif #if 1 #define JD_ASSERT(cond) \ do { \ if (!(cond)) { \ jd_assert_fail(#cond, __FILE__, __LINE__, __func__); \ } \ } while (0) #else #define JD_ASSERT(cond) ((void)0) #endif #define JD_PANIC() jd_panic_core(__FILE__, __LINE__, __func__) // never compiled out #define JD_CHK(call) \ do { \ if ((call) != 0) { \ jd_assert_fail(#call, __FILE__, __LINE__, __func__); \ } \ } while (0) // jd_queue.c typedef struct jd_queue *jd_queue_t; jd_queue_t jd_queue_alloc(unsigned size); int jd_queue_push(jd_queue_t q, jd_frame_t *pkt); jd_frame_t *jd_queue_front(jd_queue_t q); void jd_queue_shift(jd_queue_t q); void jd_queue_test(void); int jd_queue_will_fit(jd_queue_t q, unsigned size); void jd_queue_clear(jd_queue_t q); // jd_bqueue.c typedef struct jd_bqueue *jd_bqueue_t; jd_bqueue_t jd_bqueue_alloc(unsigned size); unsigned jd_bqueue_occupied_bytes(jd_bqueue_t q); unsigned jd_bqueue_free_bytes(jd_bqueue_t q); // returns 0 on success, -1 when full int jd_bqueue_push(jd_bqueue_t q, const void *data, unsigned len); // returns 0 if `size` bytes was popped, and -1 when nothing was popped int jd_bqueue_pop_atomic(jd_bqueue_t q, void *dst, unsigned size); // returns number of bytes popped unsigned jd_bqueue_pop_at_most(jd_bqueue_t q, void *dst, unsigned maxsize); // returns -1 when empty int jd_bqueue_pop_byte(jd_bqueue_t q); // low-level, not thread-safe interface unsigned jd_bqueue_available_cont_data(jd_bqueue_t q); uint8_t *jd_bqueue_cont_data_ptr(jd_bqueue_t q); void jd_bqueue_cont_data_advance(jd_bqueue_t q, unsigned sz); void jd_bqueue_print(jd_bqueue_t q, void (*print_fn)(char ch)); void jd_bqueue_clear(jd_bqueue_t q); void jd_utoa(unsigned k, char *s); void jd_itoa(int n, char *s); void jd_string_reverse(char *s); int jd_vsprintf(char *dst, unsigned dstsize, const char *format, va_list ap); __attribute__((format(printf, 3, 4))) int jd_sprintf(char *dst, unsigned dstsize, const char *format, ...); int jd_atoi(const char *s); void jd_word_move(void *dst, const void *src, unsigned numwords); void jd_log_packet(jd_packet_t *pkt); void jd_device_short_id(char short_id[5], uint64_t long_id); #endif