13void pc_uper_writer_init(UperWriter *w, uint8_t *buf,
size_t cap)
18 w->ok = (buf !=
nullptr && cap > 0);
22 for (
size_t i = 0; i < cap; i++)
29size_t pc_uper_writer_finish(UperWriter *w)
35 return (w->bit_pos + 7) / 8;
38void pc_uper_put_bits(UperWriter *w, uint32_t value,
unsigned nbits)
40 if (!w->ok || nbits == 0)
44 if (w->bit_pos + nbits > w->cap * 8)
49 for (
unsigned i = 0; i < nbits; i++)
51 unsigned bit = (value >> (nbits - 1 - i)) & 1u;
54 size_t p = w->bit_pos + i;
55 w->buf[p / 8] |= (uint8_t)(0x80u >> (p % 8));
61void pc_uper_put_bool(UperWriter *w,
bool v)
63 pc_uper_put_bits(w, v ? 1 : 0, 1);
66unsigned pc_uper_cint_bits(int64_t lo, int64_t hi)
72 uint64_t range = (uint64_t)(hi - lo);
74 while (((uint64_t)1 << bits) <= range)
81void pc_uper_put_cint(UperWriter *w, int64_t value, int64_t lo, int64_t hi)
83 unsigned bits = pc_uper_cint_bits(lo, hi);
88 uint64_t off = (uint64_t)(value - lo);
90 pc_uper_put_bits(w, (uint32_t)off, bits);
93void pc_uper_reader_init(UperReader *r,
const uint8_t *buf,
size_t nbits)
98 r->ok = (buf !=
nullptr);
101uint32_t pc_uper_get_bits(UperReader *r,
unsigned nbits)
103 if (!r->ok || nbits == 0)
107 if (r->bit_pos + nbits > r->nbits)
113 for (
unsigned i = 0; i < nbits; i++)
115 size_t p = r->bit_pos + i;
116 unsigned bit = (r->buf[p / 8] >> (7 - (p % 8))) & 1u;
123bool pc_uper_get_bool(UperReader *r)
125 return pc_uper_get_bits(r, 1) != 0;
128int64_t pc_uper_get_cint(UperReader *r, int64_t lo, int64_t hi)
130 unsigned bits = pc_uper_cint_bits(lo, hi);
135 uint32_t off = pc_uper_get_bits(r, bits);
136 return lo + (int64_t)off;
139size_t pc_j2735_bsm_core_encode(
const J2735BsmCore *c, uint8_t *out,
size_t cap)
146 pc_uper_writer_init(&w, out, cap);
147 pc_uper_put_cint(&w, c->msg_count, 0, 127);
148 pc_uper_put_bits(&w, c->id, 32);
149 pc_uper_put_cint(&w, c->sec_mark, 0, 65535);
150 pc_uper_put_cint(&w, c->lat, -900000000, 900000001);
151 pc_uper_put_cint(&w, c->lon, -1799999999, 1800000001);
152 pc_uper_put_cint(&w, c->elev, -4096, 61439);
153 pc_uper_put_cint(&w, c->speed, 0, 8191);
154 pc_uper_put_cint(&w, c->heading, 0, 28800);
155 return pc_uper_writer_finish(&w);
158bool pc_j2735_bsm_core_decode(
const uint8_t *in,
size_t len, J2735BsmCore *c)
165 pc_uper_reader_init(&r, in, len * 8);
166 c->msg_count = (uint8_t)pc_uper_get_cint(&r, 0, 127);
167 c->id = pc_uper_get_bits(&r, 32);
168 c->sec_mark = (uint16_t)pc_uper_get_cint(&r, 0, 65535);
169 c->lat = (int32_t)pc_uper_get_cint(&r, -900000000, 900000001);
170 c->lon = (int32_t)pc_uper_get_cint(&r, -1799999999, 1800000001);
171 c->elev = (int32_t)pc_uper_get_cint(&r, -4096, 61439);
172 c->speed = (uint16_t)pc_uper_get_cint(&r, 0, 8191);
173 c->heading = (uint16_t)pc_uper_get_cint(&r, 0, 28800);
177size_t pc_j2735_spat_encode(
const J2735MovementState *states,
size_t count, uint8_t *out,
size_t cap)
179 if (!out || (count && !states) || count > 31)
184 pc_uper_writer_init(&w, out, cap);
185 pc_uper_put_cint(&w, (int64_t)count, 0, 31);
186 for (
size_t i = 0; i < count; i++)
188 pc_uper_put_cint(&w, states[i].signal_group, 0, 255);
189 pc_uper_put_cint(&w, states[i].phase, 0, 9);
190 pc_uper_put_cint(&w, states[i].min_end_time, 0, 36000);
191 pc_uper_put_cint(&w, states[i].max_end_time, 0, 36000);
193 return pc_uper_writer_finish(&w);
196bool pc_j2735_spat_decode(
const uint8_t *in,
size_t len, J2735MovementState *out_states,
size_t max_states,
199 if (!in || !out_states || !out_count)
204 pc_uper_reader_init(&r, in, len * 8);
205 size_t count = (size_t)pc_uper_get_cint(&r, 0, 31);
206 if (!r.ok || count > max_states)
210 for (
size_t i = 0; i < count; i++)
212 out_states[i].signal_group = (uint8_t)pc_uper_get_cint(&r, 0, 255);
213 out_states[i].phase = (uint8_t)pc_uper_get_cint(&r, 0, 9);
214 out_states[i].min_end_time = (uint16_t)pc_uper_get_cint(&r, 0, 36000);
215 out_states[i].max_end_time = (uint16_t)pc_uper_get_cint(&r, 0, 36000);
225size_t pc_j2735_map_encode(
const J2735MapIntersection *isect,
const J2735Lane *lanes,
size_t count, uint8_t *out,
228 if (!isect || !out || (count && !lanes) || count > 31)
233 pc_uper_writer_init(&w, out, cap);
234 pc_uper_put_cint(&w, isect->intersection_id, 0, 65535);
235 pc_uper_put_cint(&w, isect->ref_lat, 0, 65535);
236 pc_uper_put_cint(&w, isect->ref_lon, 0, 65535);
237 pc_uper_put_cint(&w, (int64_t)count, 0, 31);
238 for (
size_t i = 0; i < count; i++)
240 pc_uper_put_cint(&w, lanes[i].lane_id, 0, 255);
241 pc_uper_put_bool(&w, lanes[i].is_ingress);
242 pc_uper_put_cint(&w, lanes[i].node_x, -2048, 2047);
243 pc_uper_put_cint(&w, lanes[i].node_y, -2048, 2047);
245 return pc_uper_writer_finish(&w);
248bool pc_j2735_map_decode(
const uint8_t *in,
size_t len, J2735MapIntersection *isect, J2735Lane *out_lanes,
249 size_t max_lanes,
size_t *out_count)
251 if (!in || !isect || !out_lanes || !out_count)
256 pc_uper_reader_init(&r, in, len * 8);
257 isect->intersection_id = (uint16_t)pc_uper_get_cint(&r, 0, 65535);
258 isect->ref_lat = (uint16_t)pc_uper_get_cint(&r, 0, 65535);
259 isect->ref_lon = (uint16_t)pc_uper_get_cint(&r, 0, 65535);
260 size_t count = (size_t)pc_uper_get_cint(&r, 0, 31);
261 if (!r.ok || count > max_lanes)
265 for (
size_t i = 0; i < count; i++)
267 out_lanes[i].lane_id = (uint8_t)pc_uper_get_cint(&r, 0, 255);
268 out_lanes[i].is_ingress = pc_uper_get_bool(&r);
269 out_lanes[i].node_x = (int16_t)pc_uper_get_cint(&r, -2048, 2047);
270 out_lanes[i].node_y = (int16_t)pc_uper_get_cint(&r, -2048, 2047);
SAE J2735 V2X - ASN.1 UPER primitive codec + Basic Safety Message core (PC_ENABLE_J2735).