13void uper_writer_init(UperWriter *w, uint8_t *buf,
size_t cap)
18 w->ok = (buf !=
nullptr && cap > 0);
21 for (
size_t i = 0; i < cap; i++)
25size_t uper_writer_finish(UperWriter *w)
29 return (w->bit_pos + 7) / 8;
32void uper_put_bits(UperWriter *w, uint32_t value,
unsigned nbits)
34 if (!w->ok || nbits == 0)
36 if (w->bit_pos + nbits > w->cap * 8)
41 for (
unsigned i = 0; i < nbits; i++)
43 unsigned bit = (value >> (nbits - 1 - i)) & 1u;
46 size_t p = w->bit_pos + i;
47 w->buf[p / 8] |= (uint8_t)(0x80u >> (p % 8));
53void uper_put_bool(UperWriter *w,
bool v)
55 uper_put_bits(w, v ? 1 : 0, 1);
58unsigned uper_cint_bits(int64_t lo, int64_t hi)
62 uint64_t range = (uint64_t)(hi - lo);
64 while (((uint64_t)1 << bits) <= range)
69void uper_put_cint(UperWriter *w, int64_t value, int64_t lo, int64_t hi)
71 unsigned bits = uper_cint_bits(lo, hi);
74 uint64_t off = (uint64_t)(value - lo);
76 uper_put_bits(w, (uint32_t)off, bits);
79void uper_reader_init(UperReader *r,
const uint8_t *buf,
size_t nbits)
84 r->ok = (buf !=
nullptr);
87uint32_t uper_get_bits(UperReader *r,
unsigned nbits)
89 if (!r->ok || nbits == 0)
91 if (r->bit_pos + nbits > r->nbits)
97 for (
unsigned i = 0; i < nbits; i++)
99 size_t p = r->bit_pos + i;
100 unsigned bit = (r->buf[p / 8] >> (7 - (p % 8))) & 1u;
107bool uper_get_bool(UperReader *r)
109 return uper_get_bits(r, 1) != 0;
112int64_t uper_get_cint(UperReader *r, int64_t lo, int64_t hi)
114 unsigned bits = uper_cint_bits(lo, hi);
117 uint32_t off = uper_get_bits(r, bits);
118 return lo + (int64_t)off;
121size_t detws_j2735_bsm_core_encode(
const J2735BsmCore *c, uint8_t *out,
size_t cap)
126 uper_writer_init(&w, out, cap);
127 uper_put_cint(&w, c->msg_count, 0, 127);
128 uper_put_bits(&w, c->id, 32);
129 uper_put_cint(&w, c->sec_mark, 0, 65535);
130 uper_put_cint(&w, c->lat, -900000000, 900000001);
131 uper_put_cint(&w, c->lon, -1799999999, 1800000001);
132 uper_put_cint(&w, c->elev, -4096, 61439);
133 uper_put_cint(&w, c->speed, 0, 8191);
134 uper_put_cint(&w, c->heading, 0, 28800);
135 return uper_writer_finish(&w);
138bool detws_j2735_bsm_core_decode(
const uint8_t *in,
size_t len, J2735BsmCore *c)
143 uper_reader_init(&r, in, len * 8);
144 c->msg_count = (uint8_t)uper_get_cint(&r, 0, 127);
145 c->id = uper_get_bits(&r, 32);
146 c->sec_mark = (uint16_t)uper_get_cint(&r, 0, 65535);
147 c->lat = (int32_t)uper_get_cint(&r, -900000000, 900000001);
148 c->lon = (int32_t)uper_get_cint(&r, -1799999999, 1800000001);
149 c->elev = (int32_t)uper_get_cint(&r, -4096, 61439);
150 c->speed = (uint16_t)uper_get_cint(&r, 0, 8191);
151 c->heading = (uint16_t)uper_get_cint(&r, 0, 28800);
155size_t detws_j2735_spat_encode(
const J2735MovementState *states,
size_t count, uint8_t *out,
size_t cap)
157 if (!out || (count && !states) || count > 31)
160 uper_writer_init(&w, out, cap);
161 uper_put_cint(&w, (int64_t)count, 0, 31);
162 for (
size_t i = 0; i < count; i++)
164 uper_put_cint(&w, states[i].signal_group, 0, 255);
165 uper_put_cint(&w, states[i].phase, 0, 9);
166 uper_put_cint(&w, states[i].min_end_time, 0, 36000);
167 uper_put_cint(&w, states[i].max_end_time, 0, 36000);
169 return uper_writer_finish(&w);
172bool detws_j2735_spat_decode(
const uint8_t *in,
size_t len, J2735MovementState *out_states,
size_t max_states,
175 if (!in || !out_states || !out_count)
178 uper_reader_init(&r, in, len * 8);
179 size_t count = (size_t)uper_get_cint(&r, 0, 31);
180 if (!r.ok || count > max_states)
182 for (
size_t i = 0; i < count; i++)
184 out_states[i].signal_group = (uint8_t)uper_get_cint(&r, 0, 255);
185 out_states[i].phase = (uint8_t)uper_get_cint(&r, 0, 9);
186 out_states[i].min_end_time = (uint16_t)uper_get_cint(&r, 0, 36000);
187 out_states[i].max_end_time = (uint16_t)uper_get_cint(&r, 0, 36000);
195size_t detws_j2735_map_encode(
const J2735MapIntersection *isect,
const J2735Lane *lanes,
size_t count, uint8_t *out,
198 if (!isect || !out || (count && !lanes) || count > 31)
201 uper_writer_init(&w, out, cap);
202 uper_put_cint(&w, isect->intersection_id, 0, 65535);
203 uper_put_cint(&w, isect->ref_lat, 0, 65535);
204 uper_put_cint(&w, isect->ref_lon, 0, 65535);
205 uper_put_cint(&w, (int64_t)count, 0, 31);
206 for (
size_t i = 0; i < count; i++)
208 uper_put_cint(&w, lanes[i].lane_id, 0, 255);
209 uper_put_bool(&w, lanes[i].is_ingress);
210 uper_put_cint(&w, lanes[i].node_x, -2048, 2047);
211 uper_put_cint(&w, lanes[i].node_y, -2048, 2047);
213 return uper_writer_finish(&w);
216bool detws_j2735_map_decode(
const uint8_t *in,
size_t len, J2735MapIntersection *isect, J2735Lane *out_lanes,
217 size_t max_lanes,
size_t *out_count)
219 if (!in || !isect || !out_lanes || !out_count)
222 uper_reader_init(&r, in, len * 8);
223 isect->intersection_id = (uint16_t)uper_get_cint(&r, 0, 65535);
224 isect->ref_lat = (uint16_t)uper_get_cint(&r, 0, 65535);
225 isect->ref_lon = (uint16_t)uper_get_cint(&r, 0, 65535);
226 size_t count = (size_t)uper_get_cint(&r, 0, 31);
227 if (!r.ok || count > max_lanes)
229 for (
size_t i = 0; i < count; i++)
231 out_lanes[i].lane_id = (uint8_t)uper_get_cint(&r, 0, 255);
232 out_lanes[i].is_ingress = uper_get_bool(&r);
233 out_lanes[i].node_x = (int16_t)uper_get_cint(&r, -2048, 2047);
234 out_lanes[i].node_y = (int16_t)uper_get_cint(&r, -2048, 2047);
SAE J2735 V2X - ASN.1 UPER primitive codec + Basic Safety Message core (DETWS_ENABLE_J2735).