Keep the colleague's microbu-esp32c5 tree in this repository
obu-firmware builds against vanetza-idf from microbu-esp32c5/external, but that tree was gitignored, so a clone of this repository could not build the firmware it ships. It is now committed here as ordinary files in its own folder, microbu-esp32c5/: the colleague's commit cf4b99f plus the V2X2MAP bridge's signature verification (--trust) used on the bench. Nothing is fetched from or pushed to the colleague's repository; this repository and its remotes carry everything. The folder's own .gitignore keeps build output, downloaded components and private key material out, as it did there; the committed file set is identical to that repository's tracked files. The ESP32-C5 is still flashed from obu-firmware/, which only takes vanetza-idf from microbu-esp32c5/, so the two stay separate folders. FLASHING.md says how to take a newer version of the colleague's tree (copy it over the folder, rebuild, test, commit).
This commit is contained in:
@@ -0,0 +1,251 @@
|
||||
#include "autotalks.hpp"
|
||||
|
||||
#include <vanetza/access/g5_link_layer.hpp>
|
||||
#include <vanetza/common/serialization_buffer.hpp>
|
||||
#include <vanetza/access/ethertype.hpp>
|
||||
#include <pthread.h>
|
||||
#include <iostream>
|
||||
|
||||
#include <atlk/sdk.h>
|
||||
#include <atlk/v2x.h>
|
||||
#include <atlk/v2x_service.h>
|
||||
#include <atlk/ddm_service.h>
|
||||
#include <atlk/wdm.h>
|
||||
#include <atlk/dsm.h>
|
||||
#include <atlk/wdm_service.h>
|
||||
#include <atlk/log_service.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <extern/ref_sys.h>
|
||||
#include <extern/target_type.h>
|
||||
#include <extern/time_sync.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "autotalks_link.hpp"
|
||||
|
||||
// Update this if needed
|
||||
#define SECTON_NET_NAME "enx0002ccf00006"
|
||||
|
||||
namespace vanetza
|
||||
{
|
||||
namespace autotalks
|
||||
{
|
||||
|
||||
v2x_socket_t* v2x_socket_ptr;
|
||||
bool endRxThread = false;
|
||||
|
||||
static pthread_t v2x_rx_thread;
|
||||
static uint8_t v2x_rx_buffer[2048];
|
||||
static void* v2x_rx_thread_entry(void * arg);
|
||||
|
||||
|
||||
int autotalks_device_init(void)
|
||||
{
|
||||
atlk_rc_t rc;
|
||||
const char* arg[] = {NULL, SECTON_NET_NAME};
|
||||
/** Reference system initialization */
|
||||
#if defined(CRATON_2)
|
||||
rc = ref_sys_init_ex(1, (char**) arg);
|
||||
#elif defined(SECTON)
|
||||
rc = ref_sys_init_ex(2, (char**) arg);
|
||||
#else
|
||||
#error Wrong configuration selected.
|
||||
#endif
|
||||
|
||||
// TODO //
|
||||
// TODO: Take initialization from Autotalks basic example's main function //
|
||||
// TODO //
|
||||
#error "Autotalks device initialization code is missing"
|
||||
|
||||
v2x_socket_t *v2x_if[IF_INDEX_MAX];
|
||||
// Assign the socket to the global parameter
|
||||
v2x_socket_ptr = v2x_if[0];
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int autotalks_device_deinit(void)
|
||||
{
|
||||
endRxThread = true;
|
||||
if (v2x_socket_ptr)
|
||||
v2x_socket_delete(v2x_socket_ptr);
|
||||
|
||||
atlk_rc_t ret;
|
||||
|
||||
ret = time_sync_deinit();
|
||||
if (atlk_error(ret))
|
||||
fprintf(stderr, "Fail of time_sync_deinit(). Error: %s\n", atlk_rc_to_str(ret));
|
||||
|
||||
ret = ref_sys_deinit();
|
||||
if (atlk_error(ret))
|
||||
fprintf(stderr, "Fail of ref_sys_deinit(). Error: %s\n", atlk_rc_to_str(ret));
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
atlk_rc_t autotalks_send(const void *data_ptr, size_t data_size,
|
||||
const v2x_send_params_t *params_ptr, const atlk_wait_t *wait_ptr)
|
||||
{
|
||||
atlk_rc_t ret = 0;
|
||||
if (v2x_socket_ptr == NULL)
|
||||
fprintf(stderr, "Invalid socket.\n");
|
||||
else if (v2x_socket_ptr != NULL)
|
||||
ret = v2x_send(v2x_socket_ptr, data_ptr, data_size, params_ptr, wait_ptr);
|
||||
// Check the return value
|
||||
if (atlk_error(ret)) {
|
||||
fprintf(stderr, "v2x_send failed: %d\n", ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
atlk_rc_t autotalks_receive(void *data_ptr, size_t *data_size_ptr,
|
||||
v2x_receive_params_t *params_ptr, const atlk_wait_t *wait_ptr)
|
||||
{
|
||||
return v2x_receive(v2x_socket_ptr, data_ptr, data_size_ptr, params_ptr, wait_ptr);
|
||||
}
|
||||
|
||||
vanetza::MacAddress num_to_mac(eui48_t addr)
|
||||
{
|
||||
return vanetza::MacAddress({addr.octets[0], addr.octets[1], addr.octets[2], addr.octets[3], addr.octets[4], addr.octets[5]});
|
||||
}
|
||||
|
||||
eui48_t mac_to_num(vanetza::MacAddress addr)
|
||||
{
|
||||
eui48_t ret;
|
||||
ret.octets[0] = addr.octets[0];
|
||||
ret.octets[1] = addr.octets[1];
|
||||
ret.octets[2] = addr.octets[2];
|
||||
ret.octets[3] = addr.octets[3];
|
||||
ret.octets[4] = addr.octets[4];
|
||||
ret.octets[5] = addr.octets[5];
|
||||
return ret;
|
||||
}
|
||||
|
||||
void insert_autotalks_header_transmit(const vanetza::access::DataRequest& request, std::unique_ptr<vanetza::ChunkPacket>& packet, uint8_t* pData, uint16_t length)
|
||||
{
|
||||
// There cannot be an assignment as three dots (...) are gcc extension that does not work in g++
|
||||
// => initialize the structure manually
|
||||
//v2x_send_params_t send_params = V2X_SEND_PARAMS_INIT;
|
||||
v2x_send_params_t send_params;
|
||||
send_params.source_address = EUI48_ZERO_INIT;
|
||||
send_params.dest_address = EUI48_BCAST_INIT;
|
||||
send_params.user_priority = USER_PRIORITY_NA;
|
||||
send_params.channel_id = V2X_CHANNEL_ID_INIT;
|
||||
send_params.datarate = DATARATE_NA;
|
||||
send_params.power_dbm8 = POWER_DBM8_NA;
|
||||
send_params.transmit_diversity_power_dbm8 = POWER_DBM8_NA;
|
||||
send_params.expiry_time_ms = V2X_EXPIRY_TIME_MS_NA;
|
||||
for (uint8_t i = 0; i < RF_INDEX_MAX; i++)
|
||||
send_params.comp_data[i] = COMPENSATOR_DATA_INIT;
|
||||
|
||||
vanetza::access::G5LinkLayer link_layer;
|
||||
vanetza::access::ieee802::dot11::QosDataHeader& mac_header = link_layer.mac_header;
|
||||
mac_header.destination = request.destination_addr;
|
||||
mac_header.source = request.source_addr;
|
||||
mac_header.qos_control.user_priority(request.access_category);
|
||||
|
||||
send_params.dest_address = mac_to_num(request.destination_addr);
|
||||
send_params.source_address = mac_to_num(request.source_addr);
|
||||
//mac_header.qos_control.user_priority(request.access_category);
|
||||
//send_params.user_priority = mac_header.qos_control.raw; TODO later
|
||||
|
||||
/* Set TX power to -10 dB */
|
||||
send_params.power_dbm8 = -80;
|
||||
|
||||
/* Set user priority */
|
||||
send_params.user_priority = 0;
|
||||
|
||||
/* Set default data rate */
|
||||
send_params.datarate = DATARATE_DEFAULT_VALUE;
|
||||
|
||||
vanetza::ByteBuffer link_layer_buffer;
|
||||
vanetza::serialize_into_buffer(link_layer, link_layer_buffer);
|
||||
|
||||
vanetza::ByteBuffer buffer;
|
||||
packet->layer(vanetza::OsiLayer::Physical).convert(buffer);
|
||||
|
||||
autotalks_send(pData, length, &send_params, NULL);
|
||||
}
|
||||
|
||||
boost::optional<vanetza::EthernetHeader> strip_autotalks_rx_header(vanetza::CohesivePacket& packet, v2x_receive_params_t rx_params)
|
||||
{
|
||||
vanetza::access::G5LinkLayer link_layer;
|
||||
vanetza::ByteBuffer link_layer_buffer;
|
||||
link_layer.mac_header.destination = num_to_mac(rx_params.dest_address);
|
||||
link_layer.mac_header.source = num_to_mac(rx_params.source_address);
|
||||
link_layer.llc_snap_header.protocol_id = vanetza::access::ethertype::GeoNetworking;
|
||||
vanetza::serialize_into_buffer(link_layer, link_layer_buffer);
|
||||
assert(link_layer_buffer.size() == vanetza::access::G5LinkLayer::length_bytes);
|
||||
|
||||
const vanetza::ByteBuffer& data_buffer = packet.buffer();
|
||||
vanetza::ByteBuffer final;
|
||||
for (auto i : link_layer_buffer)
|
||||
final.push_back(i);
|
||||
for (auto i : data_buffer)
|
||||
final.push_back(i);
|
||||
|
||||
vanetza::CohesivePacket finalPkt(final, vanetza::OsiLayer::Physical);
|
||||
finalPkt.set_boundary(vanetza::OsiLayer::Physical, 0);
|
||||
finalPkt.set_boundary(vanetza::OsiLayer::Link, vanetza::access::G5LinkLayer::length_bytes);
|
||||
finalPkt.set_boundary(vanetza::OsiLayer::Network, packet.size());
|
||||
|
||||
packet.set_boundary(vanetza::OsiLayer::Physical, 0);
|
||||
packet.set_boundary(vanetza::OsiLayer::Link, vanetza::access::G5LinkLayer::length_bytes);
|
||||
|
||||
packet = finalPkt;
|
||||
|
||||
vanetza::EthernetHeader eth;
|
||||
eth.destination = num_to_mac(rx_params.dest_address);
|
||||
eth.source = num_to_mac(rx_params.source_address);
|
||||
eth.type = vanetza::access::ethertype::GeoNetworking; // This is set in the Autotalks API initialization
|
||||
|
||||
return eth;
|
||||
}
|
||||
|
||||
static void* v2x_rx_thread_entry(void * arg)
|
||||
{
|
||||
AutotalksLink* link = (AutotalksLink*) arg;
|
||||
atlk_rc_t rc;
|
||||
(void) arg;
|
||||
v2x_receive_params_t rx_params;
|
||||
size_t rx_buffer_size;
|
||||
|
||||
while (!endRxThread) {
|
||||
rx_buffer_size = sizeof(v2x_rx_buffer);
|
||||
atlk_wait_t wait = {ATLK_WAIT_TYPE_INTERVAL, 100000};
|
||||
rc = autotalks_receive(v2x_rx_buffer, &rx_buffer_size, &rx_params, &wait);
|
||||
if (rc == ATLK_E_TIMEOUT)
|
||||
continue;
|
||||
else if (atlk_error(rc)) {
|
||||
std::cerr << "Receive failed: " << rc << ", " << atlk_rc_to_str(rc) << ", RX thread ends." << std::endl;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
std::cout << "Autotalks receive successful" << std::endl;
|
||||
if (nullptr != link)
|
||||
link->data_received(v2x_rx_buffer, rx_buffer_size, rx_params);
|
||||
}
|
||||
usleep(1000);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void init_rx(AutotalksLink* link_layer)
|
||||
{
|
||||
// Create new thread as Autotalks API does not have asynchronous callbacks
|
||||
int rv = pthread_create(&v2x_rx_thread, NULL, v2x_rx_thread_entry, link_layer);
|
||||
if (0 != rv) {
|
||||
fprintf(stderr, "pthread_create failed with %s\n", strerror(rv));
|
||||
}
|
||||
printf("pthread_create success!\n");
|
||||
}
|
||||
|
||||
} // namespace autotalks
|
||||
} // namespace vanetza
|
||||
|
||||
Reference in New Issue
Block a user