Pico Core
Loading...
Searching...
No Matches
harp_core.h
Go to the documentation of this file.
1#ifndef HARP_CORE_H
2#define HARP_CORE_H
3#include <stdint.h>
4#include <harp_message.h>
5#include <core_registers.h>
6#include <harp_synchronizer.h>
7#include <arm_regs.h>
8#include <cstring> // for memcpy
9#include <tusb.h>
10
11// Pico-specific includes.
12#include <hardware/structs/timer.h>
13#include <pico/divider.h> // for fast hardware division with remainder.
14#include <hardware/timer.h>
15#include <pico/unique_id.h>
16#include <pico/bootrom.h>
17
18#define HARP_VERSION_MAJOR (0)
19#define HARP_VERSION_MINOR (0)
20#define HARP_VERSION_PATCH (0)
21
22
23#define NO_PC_INTERVAL_US (3'000'000UL) // Threshold duration. If the connection
24 // with the PC has been inactive for
25 // this duration, op mode should switch
26 // to IDLE.
27#define HEARTBEAT_ACTIVE_INTERVAL_US (1'000'000UL)
28#define HEARTBEAT_STANDBY_INTERVAL_US (3'000'000UL)
29
30// Create a typedef to simplify syntax for array of static function ptrs.
31typedef void (*read_reg_fn)(uint8_t reg);
32typedef void (*write_reg_fn)(msg_t& msg);
33
34// Convenience struct for aggregating an array of fn ptrs to handle each
35// register.
41
48{
49// Make constructor protected to prevent creating instances outside of init().
50protected: // protected, but not private, to enable derived class usage.
51 HarpCore(uint16_t who_am_i,
52 uint8_t hw_version_major, uint8_t hw_version_minor,
53 uint8_t assembly_version,
54 uint8_t harp_version_major, uint8_t harp_version_minor,
55 uint8_t fw_version_major, uint8_t fw_version_minor,
56 uint16_t serial_number, const char name[],
57 const uint8_t tag[]);
58
59 ~HarpCore();
60
61public:
62 HarpCore() = delete; // Disable default constructor.
63 HarpCore(HarpCore& other) = delete; // Disable copy constructor.
64 void operator=(const HarpCore& other) = delete; // Disable assignment operator.
65
71 static HarpCore& init(uint16_t who_am_i,
72 uint8_t hw_version_major, uint8_t hw_version_minor,
73 uint8_t assembly_version,
74 uint8_t harp_version_major, uint8_t harp_version_minor,
75 uint8_t fw_version_major, uint8_t fw_version_minor,
76 uint16_t serial_number, const char name[],
77 const uint8_t tag[]);
78
79 static inline HarpCore* self = nullptr; // pointer to the singleton instance.
80 static HarpCore& instance() {return *self;}
81
82
88 void run();
89
96
102
107
111 bool new_msg()
112 {return new_msg_;}
113
119 {new_msg_ = false;}
120
132 static void write_reg_generic(msg_t& msg);
133
140 static void read_reg_generic(uint8_t reg_name);
141
146 static void write_to_read_only_reg_error(msg_t& msg);
147
152 static inline void copy_msg_payload_to_register(msg_t& msg)
153 {
154 const RegSpecs& specs = self->reg_address_to_specs(msg.header.address);
155 memcpy((void*)specs.base_ptr, msg.payload, specs.num_bytes);
156 }
157
172 static void send_harp_reply(msg_type_t reply_type, uint8_t reg_name,
173 const volatile uint8_t* data, uint8_t num_bytes,
174 reg_type_t payload_type, uint64_t harp_time_us);
175
189 static inline void send_harp_reply(msg_type_t reply_type, uint8_t reg_name,
190 const volatile uint8_t* data,
191 uint8_t num_bytes,
192 reg_type_t payload_type)
193 {return send_harp_reply(reply_type, reg_name, data, num_bytes, payload_type,
194 harp_time_us_64());}
195
207 static inline void send_harp_reply(msg_type_t reply_type, uint8_t reg_name)
208 {
209 const RegSpecs& specs = self->reg_address_to_specs(reg_name);
210 send_harp_reply(reply_type, reg_name, specs.base_ptr, specs.num_bytes,
211 specs.payload_type);
212 }
213
224 static inline void send_harp_reply(msg_type_t reply_type, uint8_t reg_name,
225 uint64_t harp_time_us)
226 {
227 const RegSpecs& specs = self->reg_address_to_specs(reg_name);
228 send_harp_reply(reply_type, reg_name, specs.base_ptr, specs.num_bytes,
229 specs.payload_type, harp_time_us);
230 }
231
232
233
237 static inline bool is_muted()
238 {return bool((self->regs.R_OPERATION_CTRL >> MUTE_RPL_OFFSET) & 0x01);}
239
247 static inline bool is_synced()
248 {
249 return (self->sync_ == nullptr)?
250 false:
251 self->sync_->is_synced();
252 }
253
258 static inline bool events_enabled()
259 {return (self->regs.R_OPERATION_CTRL & 0x03) == ACTIVE;}
260
269 static inline uint64_t harp_time_us_64()
270 {return system_to_harp_us_64(time_us_64());}
271
277 static inline uint32_t harp_time_s()
278 {
279 self->update_timestamp_regs(); // calls harp_time_us_64() internally.
281 }
282
293 static inline uint64_t harp_to_system_us_64(uint64_t harp_time_us)
294 {return (self->sync_ == nullptr)?
295 harp_time_us + self->offset_us_64_:
296 self->sync_->harp_to_system_us_64(harp_time_us);}
297
308 static inline uint32_t harp_to_system_us_32(uint64_t harp_time_us)
309 {return uint32_t(harp_to_system_us_64(harp_time_us));}
310
322 static inline uint64_t system_to_harp_us_64(uint64_t system_time_us)
323 {return (self->sync_ == nullptr)?
324 system_time_us - self->offset_us_64_:
325 self->sync_->system_to_harp_us_64(system_time_us);}
326
335 static inline void set_harp_time_us_64(uint64_t harp_time_us)
336 {if (self->sync_ != nullptr)
337 self->sync_->set_harp_time_us_64(harp_time_us);
338 self->offset_us_64_ = time_us_64() - harp_time_us;}
339
345 static void set_synchronizer(HarpSynchronizer* sync)
346 {self->sync_ = sync;}
347
352 static void set_visual_indicators_fn(void (*func)(bool))
354
358 static void force_state(op_mode_t next_state)
359 {self->update_state(true, next_state);}
360
371 static void set_uuid(uint8_t* uuid, size_t num_bytes, size_t offset = 0)
372 {
373 memset(self->regs.R_UUID, 0, sizeof(self->regs.R_UUID));
374 memcpy((void*)(&self->regs.R_UUID[offset]), (void*)uuid, num_bytes);
375 }
376
377protected:
383
390
396 virtual void update_app_state(){};
397
403 virtual void reset_app(){};
404
408 void set_visual_indicators(bool enabled)
409 {if (set_visual_indicators_fn_ != nullptr)
411
418 virtual void dump_app_registers(){};
419
420 virtual const RegSpecs& address_to_app_reg_specs(uint8_t address)
421 {return regs_.address_to_specs[0];} // should never happen.
422
427
432
436 HarpSynchronizer* sync_;
437
438private:
443 uint64_t curr_harp_time_us)
444 {
445 // Recompute next whole second (in [us]) based on synchronized time.
446 // Round *up* to the nearest whole second.
447#if defined(PICO_RP2040) // Invoke pico-specific fast-integer-division hardware.
448 uint64_t remainder;
449 uint64_t quotient = divmod_u64u64_rem(curr_harp_time_us, 1'000'000ULL,
450 &remainder);
451 #else
452 uint64_t remainder = curr_harp_time_us % 1'000'000ULL;
453 #endif
455 harp_to_system_us_32(curr_harp_time_us - remainder)
457 }
462 const uint8_t& total_bytes_read_;
463
468
473
482
490
496
504
510
516
522
528 void process_cdc_input();
529
537 static void update_state(bool force = false,
538 op_mode_t forced_next_state = STANDBY);
539
540
545 static inline void update_timestamp_regs()
547
548
552 static void set_timestamp_regs(uint64_t harp_time_us);
553
560 const RegSpecs& reg_address_to_specs(uint8_t address);
561
562 // core register read handler functions. Handles read operations on those
563 // registers. One-per-harp-register where necessary, but read_reg_generic()
564 // can be used in most cases.
565 // Note: these all need to have the same function signature.
566 static void read_timestamp_second(uint8_t reg_name);
567 static void read_timestamp_microsecond(uint8_t reg_name);
568
569
570 // write handler function per core register. Handles write
571 // operations to that register.
572 // Note: these all need to have the same function signature.
573
578 static void write_timestamp_second(msg_t& msg);
579
584 static void write_timestamp_microsecond(msg_t& msg);
585
586 static void write_operation_ctrl(msg_t& msg);
587 static void write_reset_dev(msg_t& msg);
588 static void write_device_name(msg_t& msg);
589 static void write_serial_number(msg_t& msg);
590 static void write_clock_config(msg_t& msg);
591 static void write_timestamp_offset(msg_t& msg);
592
594
621};
622
623#endif //HARP_CORE_H
Harp Core that handles management of common bank registers. Implemented as a singleton to simplify at...
Definition harp_core.h:48
void process_cdc_input()
Read incoming bytes from the USB serial port. Does not block.
Definition harp_core.cpp:94
static void write_device_name(msg_t &msg)
Definition harp_core.cpp:475
static void copy_msg_payload_to_register(msg_t &msg)
update local (app or core) register data with the payload provided in the input msg.
Definition harp_core.h:152
uint8_t rx_buffer_index_
rx_buffer_ index where the next incoming byte will be written.
Definition harp_core.h:472
static uint64_t harp_time_us_64()
get the total elapsed microseconds (64-bit) in "Harp" time.
Definition harp_core.h:269
msg_header_t & get_buffered_msg_header()
return a reference to the message header in the rx_buffer_.
Definition harp_core.h:94
static void write_operation_ctrl(msg_t &msg)
Definition harp_core.cpp:416
virtual void update_app_state()
update state of the derived class. Does nothing in the base class, but not pure virtual since we need...
Definition harp_core.h:396
uint32_t disconnect_start_time_us_
last time device detects no connection with the PC in microseconds.
Definition harp_core.h:503
uint64_t offset_us_64_
local offset from "Harp time" to device hardware timer tracing elapsed microseconds since boot,...
Definition harp_core.h:481
bool new_msg()
flag indicating whether or not a new message is in the rx_buffer_.
Definition harp_core.h:111
static void read_reg_generic(uint8_t reg_name)
generic handler function to read a message payload to a core or app register and issue a harp reply (...
Definition harp_core.cpp:313
bool connect_handled_
flag to indicate the the device was connected and the event has been handled.
Definition harp_core.h:515
virtual void handle_buffered_app_message()
Handle incoming messages for the derived class. Does nothing here, but not pure virtual since we need...
Definition harp_core.h:389
static void send_harp_reply(msg_type_t reply_type, uint8_t reg_name, const volatile uint8_t *data, uint8_t num_bytes, reg_type_t payload_type, uint64_t harp_time_us)
Construct and send a Harp-compliant timestamped reply message from provided arguments.
Definition harp_core.cpp:248
~HarpCore()
Definition harp_core.cpp:51
RegValues & regs
reference to the struct of reg values for easy access.
Definition harp_core.h:106
bool new_msg_
flag indicating whether or not a new message is in the rx_buffer_.
Definition harp_core.h:426
virtual void reset_app()
reset the app. Called when the writing to the RESET_DEF register. Does nothing in the base class,...
Definition harp_core.h:403
static void set_visual_indicators_fn(void(*func)(bool))
attach a callback function to control external visual indicators (i.e: LEDs).
Definition harp_core.h:352
bool disconnect_handled_
flag to indicate the the device was disconnected and the event has been handled.
Definition harp_core.h:509
virtual void dump_app_registers()
send one harp reply read message per app register. Called when the writing to the R_OPERATION_CTRL's ...
Definition harp_core.h:418
HarpCore(HarpCore &other)=delete
void set_visual_indicators(bool enabled)
Enable or disable external virtual indicators.
Definition harp_core.h:408
static void write_timestamp_second(msg_t &msg)
Handle writing to the R_TIMESTAMP_SECOND register and update the device's Harp time to reflect the se...
Definition harp_core.cpp:364
HarpSynchronizer * sync_
function pointer to synchronizer if configured.
Definition harp_core.h:436
Registers regs_
struct of Harp core registers
Definition harp_core.h:593
static uint32_t harp_to_system_us_32(uint64_t harp_time_us)
convert harp time (in 32-bit microseconds) to local system time (in 32-bit microseconds).
Definition harp_core.h:308
static HarpCore * self
Definition harp_core.h:79
HarpCore()=delete
static void set_uuid(uint8_t *uuid, size_t num_bytes, size_t offset=0)
set the 16 bytews in the R_UUID register. Any unspecified bytes will be set to zero....
Definition harp_core.h:371
RegFnPair reg_func_table_[CORE_REG_COUNT]
Function table containing the read/write handler functions, one pair per core register....
Definition harp_core.h:599
static void send_harp_reply(msg_type_t reply_type, uint8_t reg_name, const volatile uint8_t *data, uint8_t num_bytes, reg_type_t payload_type)
Construct and send a Harp-compliant timestamped reply message from provided arguments....
Definition harp_core.h:189
virtual const RegSpecs & address_to_app_reg_specs(uint8_t address)
Definition harp_core.h:420
static void write_reg_generic(msg_t &msg)
generic handler function to write a message payload to a core or app register and issue a harp reply ...
Definition harp_core.cpp:319
void operator=(const HarpCore &other)=delete
bool sync_handled_
true if the device has synchronized and all consequential activity has been handled.
Definition harp_core.h:521
static void read_timestamp_microsecond(uint8_t reg_name)
Definition harp_core.cpp:389
static void read_timestamp_second(uint8_t reg_name)
Definition harp_core.cpp:358
void clear_msg()
flag that new message has been handled. Inline.
Definition harp_core.h:118
static void set_timestamp_regs(uint64_t harp_time_us)
Write the a specified Harp time to the timestamp registers.
Definition harp_core.cpp:338
static bool events_enabled()
true if the "events enabled" flag has been set in the R_OPERATION_CTRL register.
Definition harp_core.h:258
static void send_harp_reply(msg_type_t reply_type, uint8_t reg_name)
Construct and send a Harp-compliant timestamped reply message where payload data is written from the ...
Definition harp_core.h:207
void run()
Periodically handle tasks based on the current time, state, and inputs. Should be called in a loop....
Definition harp_core.cpp:53
static void update_state(bool force=false, op_mode_t forced_next_state=STANDBY)
update internal state machine.
Definition harp_core.cpp:159
static void update_next_heartbeat_from_curr_harp_time_us(uint64_t curr_harp_time_us)
recompute the next heartbeat event time based on the current time.
Definition harp_core.h:442
static void write_reset_dev(msg_t &msg)
Definition harp_core.cpp:447
void handle_buffered_core_message()
entry point for handling incoming harp messages to core registers. Dispatches message to the appropri...
Definition harp_core.cpp:138
static void write_to_read_only_reg_error(msg_t &msg)
write handler function. Sends a harp reply indicating a write error to the specified register.
Definition harp_core.cpp:330
static bool is_muted()
true if the mute flag has been set in the R_OPERATION_CTRL register.
Definition harp_core.h:237
static void write_clock_config(msg_t &msg)
Definition harp_core.cpp:490
const uint8_t & total_bytes_read_
the total number of bytes read into the the msg receive buffer. This is implemented as a read-only re...
Definition harp_core.h:462
static void force_state(op_mode_t next_state)
force the op mode state. Useful to put the core in an error state.
Definition harp_core.h:358
uint32_t heartbeat_interval_us_
the current interval at which the next_neartbeat_time_us_ is being updated.
Definition harp_core.h:495
static void set_synchronizer(HarpSynchronizer *sync)
attach a synchronizer. If the synchronizer is attached, then calls to harp_time_us_64() and harp_time...
Definition harp_core.h:345
static void set_harp_time_us_64(uint64_t harp_time_us)
Override the current Harp time with a specific time.
Definition harp_core.h:335
static uint64_t system_to_harp_us_64(uint64_t system_time_us)
convert system time (in 64-bit microseconds) to local system time (in 64-bit microseconds).
Definition harp_core.h:322
static void send_harp_reply(msg_type_t reply_type, uint8_t reg_name, uint64_t harp_time_us)
Send a Harp-compliant reply with a specific timestamp.
Definition harp_core.h:224
static void write_serial_number(msg_t &msg)
Definition harp_core.cpp:484
static void write_timestamp_microsecond(msg_t &msg)
Handle writing to the R_TIMESTAMP_MICROSECOND register and update the device's Harp time to reflect t...
Definition harp_core.cpp:396
const RegSpecs & reg_address_to_specs(uint8_t address)
return a reference to the specified core or app register's specs used for issuing a harp reply for th...
Definition harp_core.cpp:241
static uint32_t harp_time_s()
get the current elapsed seconds in "Harp" time.
Definition harp_core.h:277
static bool is_synced()
true if the device is synchronized via external CLKIN input.
Definition harp_core.h:247
static uint64_t harp_to_system_us_64(uint64_t harp_time_us)
convert harp time (in 64-bit microseconds) to local system time (in 64-bit microseconds).
Definition harp_core.h:293
static HarpCore & instance()
returns the singleton.
Definition harp_core.h:80
static void update_timestamp_regs()
Write the current Harp time to the timestamp registers.
Definition harp_core.h:545
uint8_t rx_buffer_[MAX_PACKET_SIZE]
buffer to contain data read from the serial port.
Definition harp_core.h:467
msg_t get_buffered_msg()
return a reference to the message in the rx_buffer_. Inline.
Definition harp_core.cpp:128
void(* set_visual_indicators_fn_)(bool)
function pointer to function that enables/disables visual indicators.
Definition harp_core.h:431
uint32_t next_heartbeat_time_us_
next time a heartbeat message is scheduled to issue.
Definition harp_core.h:489
static void write_timestamp_offset(msg_t &msg)
Definition harp_core.cpp:496
static HarpCore & init(uint16_t who_am_i, uint8_t hw_version_major, uint8_t hw_version_minor, uint8_t assembly_version, uint8_t harp_version_major, uint8_t harp_version_minor, uint8_t fw_version_major, uint8_t fw_version_minor, uint16_t serial_number, const char name[], const uint8_t tag[])
initialize the harp core singleton with parameters and init Tinyusb.
Definition harp_core.cpp:3
static const uint8_t CORE_REG_COUNT
Definition core_registers.h:8
#define MUTE_RPL_OFFSET
Definition core_registers.h:14
op_mode_t
enum for easier interpretation of the OP_MODE bitfield in the R_OPERATION_CTRL register.
Definition core_registers.h:30
@ ACTIVE
Definition core_registers.h:32
@ STANDBY
Definition core_registers.h:31
void(* write_reg_fn)(msg_t &msg)
Definition harp_core.h:32
void(* read_reg_fn)(uint8_t reg)
Definition harp_core.h:31
msg_type_t
Definition harp_message.h:8
#define MAX_PACKET_SIZE
Definition harp_message.h:5
reg_type_t
Definition reg_types.h:11
Definition harp_core.h:37
read_reg_fn read_fn_ptr
Definition harp_core.h:38
write_reg_fn write_fn_ptr
Definition harp_core.h:39
Definition core_registers.h:90
const reg_type_t payload_type
Definition core_registers.h:93
const uint8_t num_bytes
Definition core_registers.h:92
volatile uint8_t *const base_ptr
Definition core_registers.h:91
Definition core_registers.h:67
volatile uint32_t R_TIMESTAMP_SECOND
Definition core_registers.h:76
volatile uint8_t R_OPERATION_CTRL
Definition core_registers.h:78
uint8_t R_UUID[16]
Definition core_registers.h:84
Definition core_registers.h:97
RegValues regs_
Definition core_registers.h:108
const RegSpecs address_to_specs[CORE_REG_COUNT]
Definition core_registers.h:113
Definition harp_message.h:21
uint8_t address
Definition harp_message.h:24
Definition harp_message.h:49
void * payload
Definition harp_message.h:51
msg_header_t & header
Definition harp_message.h:50