wip hscan common
parent
0ce20cb46f
commit
a482444490
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"files.associations": {
|
||||
"irq.h": "c",
|
||||
"pio.h": "c"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "hscan.h"
|
||||
|
||||
void hscan_impl_setup(hscan_bus *bus, hscan_config config);
|
||||
|
||||
void hscan_setup(hscan_bus *bus, hscan_config config) {
|
||||
memset(bus, 0, sizeof(*bus));
|
||||
|
||||
assert(config.callback);
|
||||
|
||||
if (!config.experimental_bitrate) {
|
||||
config.experimental_bitrate = HSCAN_BITRATE;
|
||||
}
|
||||
|
||||
hscan_impl_setup(bus, config);
|
||||
}
|
||||
|
||||
void hscan_impl_send(hscan_bus *bus, hscan_msg *msg);
|
||||
void hscan_send(hscan_bus *bus, hscan_msg *msg) {
|
||||
hscan_impl_send(bus, msg);
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
#ifndef _HSCAN_H
|
||||
#define _HSCAN_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "id.h"
|
||||
#include "impl.h"
|
||||
|
||||
typedef struct {
|
||||
// TBD
|
||||
hscan_bus_impl *impl;
|
||||
} hscan_bus;
|
||||
|
||||
typedef struct {
|
||||
/** Identifier (and priority) of the message */
|
||||
hscan_id id;
|
||||
/** Number of bytes of data (0-8 bytes), a.k.a. DLC */
|
||||
uint8_t length;
|
||||
/** Data bytes */
|
||||
uint8_t data[8];
|
||||
/** If `true`, this message is a RTR (Remote Transmission Request) */
|
||||
bool is_request;
|
||||
} hscan_msg;
|
||||
|
||||
#define HSCAN_BITRATE 500000
|
||||
|
||||
typedef enum {
|
||||
HSCAN_MSG_STATUS_RECEIVED = 1<<20,
|
||||
HSCAN_MSG_STATUS_TRANSMITTED = 1<<21,
|
||||
HSCAN_MSG_STATUS_ERROR = 1<<23,
|
||||
} hscan_msg_status;
|
||||
|
||||
typedef void (*hscan_callback_t)(hscan_bus *bus, hscan_msg *msg, hscan_msg_status status);
|
||||
|
||||
typedef struct {
|
||||
hscan_callback_t callback;
|
||||
hscan_impl_config impl;
|
||||
// NOTE: Optional, default should be used
|
||||
uint32_t experimental_bitrate;
|
||||
} hscan_config;
|
||||
|
||||
void hscan_setup(hscan_bus *bus, hscan_config config);
|
||||
|
||||
void hscan_send(hscan_bus *bus, hscan_msg *msg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
|
@ -1,6 +1,5 @@
|
|||
#include <assert.h>
|
||||
|
||||
#include "hscan.h"
|
||||
#include "id.h"
|
||||
|
||||
hscan_id hscan_id_make(uint32_t id) {
|
||||
assert(id < (1 << 29));
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef _HSCAN_H
|
||||
#define _HSCAN_H
|
||||
#ifndef _HSCAN_ID_H
|
||||
#define _HSCAN_ID_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
@ -14,20 +14,6 @@ typedef struct {
|
|||
bool is_extended;
|
||||
} hscan_id;
|
||||
|
||||
typedef struct {
|
||||
/** Identifier (and priority) of the message */
|
||||
hscan_id id;
|
||||
/** Number of bytes of data (0-8 bytes), a.k.a. DLC */
|
||||
uint8_t length;
|
||||
/** Data bytes */
|
||||
uint8_t data[8];
|
||||
/** If `true`, this message is a RTR (Remote Transmission Request) */
|
||||
bool is_request;
|
||||
} hscan_msg;
|
||||
|
||||
#define HSCAN_BAUDRATE 500000
|
||||
|
||||
// CAN message IDs
|
||||
#define HSCAN_ID_DEVICE_SIZE 256
|
||||
// #define HSCAN_ID_DEVICE_INFRA_MIN 0
|
||||
// #define HSCAN_ID_DEVICE_INFRA_MAX 31
|
|
@ -0,0 +1,11 @@
|
|||
#ifndef _HSCAN_IMPL_H
|
||||
#define _HSCAN_IMPL_H
|
||||
|
||||
#include "rp2040/rp2040.h"
|
||||
#include "hscan.h"
|
||||
|
||||
typedef hscan_rp2040_config hscan_impl_config;
|
||||
|
||||
typedef struct can2040 hscan_bus_impl;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,83 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#include "hardware/irq.h"
|
||||
|
||||
#include "../hscan.h"
|
||||
#include "can2040.h"
|
||||
#include "rp2040.h"
|
||||
|
||||
static struct can2040 hscan_rp2040_canbus0;
|
||||
static struct can2040 hscan_rp2040_canbus1;
|
||||
|
||||
static void hscan_rp2040_pio0_irq_handler() {
|
||||
can2040_pio_irq_handler(&hscan_rp2040_canbus0);
|
||||
}
|
||||
|
||||
static void hscan_rp2040_pio1_irq_handler() {
|
||||
can2040_pio_irq_handler(&hscan_rp2040_canbus1);
|
||||
}
|
||||
|
||||
struct can2040_msg hscan_rp2040_encode_msg(hscan_msg msg) {
|
||||
uint32_t id = msg.id.id;
|
||||
if (msg.id.is_extended) {
|
||||
id |= CAN2040_ID_EFF;
|
||||
}
|
||||
if (msg.is_request) {
|
||||
id |= CAN2040_ID_RTR;
|
||||
}
|
||||
|
||||
struct can2040_msg can_msg;
|
||||
can_msg.id = id;
|
||||
can_msg.dlc = msg.length;
|
||||
for (int i = 0; i < msg.length; i++) {
|
||||
can_msg.data[i] = msg.data[i];
|
||||
}
|
||||
return can_msg;
|
||||
}
|
||||
|
||||
hscan_msg hscan_rp2040_decode_msg(struct can2040_msg can_msg) {
|
||||
hscan_msg msg;
|
||||
msg.id.is_extended = can_msg.id & CAN2040_ID_EFF;
|
||||
msg.id.id = can_msg.id & 0x1FFFFFFF; // 29-bit mask
|
||||
msg.is_request = can_msg.id & CAN2040_ID_RTR;
|
||||
msg.length = can_msg.dlc;
|
||||
for (int i = 0; i < msg.length; i++) {
|
||||
msg.data[i] = can_msg.data[i];
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
void hscan_impl_setup(hscan_bus *bus, hscan_config config) {
|
||||
// TODO: set up bus->impl
|
||||
// TODO: Set up callback
|
||||
|
||||
uint8_t pio_num = config.impl.pio_num;
|
||||
assert(pio_num == 0 || pio_num == 1);
|
||||
|
||||
// set up can bus
|
||||
can2040_setup(bus->impl, pio_num);
|
||||
can2040_callback_config(bus->impl, NULL);
|
||||
|
||||
// set up interrupt handler
|
||||
uint irq_num = pio_num == 0 ? PIO0_IRQ_0 : PIO1_IRQ_0;
|
||||
irq_handler_t irq_handler = pio_num == 0 ?
|
||||
hscan_rp2040_pio0_irq_handler :
|
||||
hscan_rp2040_pio1_irq_handler;
|
||||
uint8_t irq_priority = config.impl.irq_priority || 1;
|
||||
|
||||
irq_set_exclusive_handler(irq_num, irq_handler);
|
||||
irq_set_priority(irq_num, irq_priority);
|
||||
irq_set_enabled(irq_num, true);
|
||||
|
||||
// start can bus
|
||||
can2040_start(bus->impl,
|
||||
config.impl.sys_clock,
|
||||
config.experimental_bitrate,
|
||||
config.impl.gpio_rx,
|
||||
config.impl.gpio_tx);
|
||||
}
|
||||
|
||||
void hscan_impl_send(hscan_bus *bus, hscan_msg *msg) {
|
||||
struct can2040_msg encoded = hscan_rp2040_encode_msg(*msg);
|
||||
can2040_transmit(bus->impl, &encoded);
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
#ifndef _HSCAN_RP2040_IMPL_H
|
||||
#define _HSCAN_RP2040_IMPL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
// #include "../hscan.h"
|
||||
|
||||
typedef struct {
|
||||
uint8_t pio_num;
|
||||
uint32_t sys_clock;
|
||||
uint8_t gpio_rx;
|
||||
uint8_t gpio_tx;
|
||||
// NOTE: Optional, defaults to 1
|
||||
uint8_t irq_priority;
|
||||
} hscan_rp2040_config;
|
||||
|
||||
#endif
|
|
@ -1,51 +1,54 @@
|
|||
#include <Arduino.h>
|
||||
|
||||
extern "C" {
|
||||
#include "can2040.h"
|
||||
#include "hscan/hscan.h"
|
||||
|
||||
static void can_callback(hscan_bus *bus, hscan_msg *msg, hscan_msg_status status) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
static struct can2040 cbus;
|
||||
static hscan_bus bus;
|
||||
|
||||
static void can2040_cb(struct can2040 *cd, uint32_t notify, struct can2040_msg *msg) {
|
||||
printf("cb ntfy status: %d\n", notify);
|
||||
}
|
||||
|
||||
static void PIOx_IRQHandler() {
|
||||
can2040_pio_irq_handler(&cbus);
|
||||
}
|
||||
|
||||
void canbus_setup()
|
||||
{
|
||||
uint32_t pio_num = 0;
|
||||
uint32_t sys_clock = 125000000, bitrate = 500000;
|
||||
uint32_t gpio_rx = 16, gpio_tx = 17;
|
||||
|
||||
// Setup canbus
|
||||
can2040_setup(&cbus, pio_num);
|
||||
can2040_callback_config(&cbus, can2040_cb);
|
||||
|
||||
// Enable irqs
|
||||
irq_set_exclusive_handler(PIO0_IRQ_0, PIOx_IRQHandler);
|
||||
// NVIC_SetPriority(PIO0_IRQ_0_IRQn, 1);
|
||||
// NVIC_EnableIRQ(PIO0_IRQ_0_IRQn);
|
||||
|
||||
// Start canbus
|
||||
can2040_start(&cbus, sys_clock, bitrate, gpio_rx, gpio_tx);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
// stdio_init_all();
|
||||
canbus_setup();
|
||||
|
||||
while (true) {
|
||||
sleep_ms(1000 + get_rand_32() % 1000);
|
||||
can2040_msg msg = {
|
||||
.id = 0x125,
|
||||
.dlc = 8,
|
||||
.data = {'P', 'A', 'P', 'I', 'E', 'S', 'Z'}
|
||||
};
|
||||
auto status = can2040_transmit(&cbus, &msg);
|
||||
printf("Transmit status: %d\n", status);
|
||||
void canbus_setup() {
|
||||
hscan_setup(&bus, {
|
||||
.callback = can_callback,
|
||||
.impl = {
|
||||
.pio_num = 0,
|
||||
.sys_clock = 125000000,
|
||||
.gpio_rx = 16,
|
||||
.gpio_tx = 17
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
canbus_setup();
|
||||
}
|
||||
|
||||
void canbus_heartbeat_loop();
|
||||
void loop() {
|
||||
canbus_heartbeat_loop();
|
||||
}
|
||||
|
||||
unsigned long canbus_last_heartbeat_at = 0;
|
||||
int canbus_heartbeat_interval = 1000;
|
||||
void canbus_heartbeat();
|
||||
|
||||
void canbus_heartbeat_loop() {
|
||||
auto now = millis();
|
||||
if (canbus_last_heartbeat_at + canbus_heartbeat_interval < now) {
|
||||
canbus_last_heartbeat_at = now;
|
||||
// add some jitter to reduce collision likelihood
|
||||
canbus_heartbeat_interval = 1000 + random(-200, 200);
|
||||
canbus_heartbeat();
|
||||
}
|
||||
}
|
||||
|
||||
void canbus_heartbeat() {
|
||||
int experimental_device_id = 1;
|
||||
|
||||
hscan_msg msg = {
|
||||
.id = hscan_id_experimental_device_heartbeat(experimental_device_id)
|
||||
};
|
||||
hscan_send(&bus, &msg);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue