jacdac-c/inc/jd_util.h

170 строки
6.6 KiB
C

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#ifndef JD_UTIL_H
#define JD_UTIL_H
#include "jd_physical.h"
#include <stdarg.h>
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