15#include "IntervalTimer.h"
40#if PP_NARG_MO(PINS_CANBUS_DIGITAL_OUT) > 8
41#error Too many digital out canPins defined
42#elif PP_NARG_MO(PINS_CANBUS_DIGITAL_IN) > 8
43#error Too many digital in canPins defined
47static std::map<uint8_t, int *> CAN_GPIO_MAP_IN;
48static int CAN_GPIO_IN[analogCanPinCount_IN + digitalCanPinCount_IN] = {0};
49static std::map<uint8_t, int> CAN_GPIO_MAP_OUT;
50static const int maxActiveDigitalPins = 8;
52static IntervalTimer canbusPinUpdate;
53static const LOG_TAG ID =
"Pins";
58 uint64_t *bufmap = (uint64_t *)buf;
61static int getOutgoingPinValue(uint8_t GPIO_Pin);
64struct digitalCanPinMsg_t : CanPinMsg_t {
65 uint32_t activedigitalCanPins = 0;
66 uint8_t digitalPins[maxActiveDigitalPins];
67 uint digitalPinPos[maxActiveDigitalPins];
70 for (
size_t i = 0; i < activedigitalCanPins; i++) {
71 *bufmap = *bufmap << 1;
72 *bufmap |= (bool)getOutgoingPinValue(digitalPins[i]);
75 Canbus::sendData(address, buf);
77 void receive(uint8_t buffer[8]) {
78 bufmap = (uint64_t *)buffer;
79 for (
int i = activedigitalCanPins - 1; i >= 0; i--) {
80 CAN_GPIO_IN[digitalPinPos[i]] = *bufmap & 1;
83 *bufmap = *bufmap >> 1;
87 Serial.printf(
"Printing outgoing digital pin values: ");
88 Serial.println(activedigitalCanPins);
89 for (
size_t i = 0; i < activedigitalCanPins; i++) {
90 Serial.print(digitalPins[i]);
92 Serial.println(getOutgoingPinValue(digitalPins[i]));
97struct analogCanPinMsg_t : CanPinMsg_t {
98 uint8_t analogPins[2] = {255, 255};
102 for (
size_t i = 0; i < 2; i++) {
103 *bufmap = *bufmap << 32;
104 if (analogPins[i] != 255)
105 *bufmap |= getOutgoingPinValue(analogPins[i]);
108 Canbus::sendData(address, buf);
110 void receive(uint8_t buffer[8]) {
111 bufmap = (uint64_t *)buffer;
112 int a0 = *bufmap >> 32;
113 int a1 = *bufmap & 0x00000000FFFFFFFF;
114 CAN_GPIO_IN[analogPinPos[0]] = a0;
115 if (analogPins[1] != 255)
116 CAN_GPIO_IN[analogPinPos[1]] = a1;
121 Serial.printf(
"Printing outgoing analog pin values for address: %u\n", address);
122 Serial.print(analogPins[0]);
124 Serial.println(getOutgoingPinValue(analogPins[0]));
125 if (analogPins[1] != 255) {
126 Serial.print(analogPins[1]);
128 Serial.println(getOutgoingPinValue(analogPins[1]));
133static digitalCanPinMsg_t digitalCanPinMessage_IN;
134static digitalCanPinMsg_t digitalCanPinMessage_OUT;
135static analogCanPinMsg_t analogCanPinMessages_IN[analogCanMsgCount_IN];
136static analogCanPinMsg_t analogCanPinMessages_OUT[analogCanMsgCount_OUT];
138#define __WRITEPIN_DIGITALOUTPUT(PIN, VAL) \
140 else if (GPIO_Pin == PIN) { \
141 return digitalWriteFast(PIN, VAL);
143#define __WRITEPIN_ANALOGOUTPUT(PIN, VAL) \
145 else if (GPIO_Pin == PIN) { \
146 return analogWrite(PIN, VAL);
148#define __READPIN_DIGITALINPUT(PIN) \
150 else if (GPIO_Pin == PIN) { \
151 return digitalReadFast(PIN);
154#define __READPIN_ANALOGINPUT(PIN) \
156 else if (GPIO_Pin == PIN) { \
157 return analogRead(PIN); \
160#define __WRITEPIN_DIGITALINPUT(PIN, VAL)
161#define __WRITEPIN_ANALOGINPUT(PIN, VAL)
162#define __READPIN_DIGITALOUTPUT(PIN)
163#define __READPIN_ANALOGOUTPUT(PIN)
168static void _receiveDigitalCanbusPin(uint32_t address,
volatile uint8_t *buffer) {
169 digitalCanPinMessage_IN.receive((uint8_t *)buffer);
172static void _receiveAnalogCanbusPin(uint32_t address,
volatile uint8_t *buffer) {
173 for (
size_t i = 0; i < analogCanMsgCount_IN; i++) {
174 if (analogCanPinMessages_IN[i].address == address) {
175 analogCanPinMessages_IN[i].receive((uint8_t *)buffer);
203#define X(pin, Type, IO, init) \
205 Serial.print(" : "); \
206 Serial.println(getPinValue(pin));
211static void _pushCanbusPins(
void) {
212 digitalCanPinMessage_OUT.send();
213 for (
size_t i = 0; i < analogCanMsgCount_OUT; i++) {
214 analogCanPinMessages_OUT[i].send();
220 if (CAN_GPIO_MAP_OUT.find(Internal_Pin) != CAN_GPIO_MAP_OUT.end()) {
221 if (CAN_GPIO_MAP_OUT[Internal_Pin] == value)
223 Log.
d(ID,
"Setting Internal pin:", Internal_Pin);
224 Log.
d(ID,
"Setting Internal pin to int:", value);
225 CAN_GPIO_MAP_OUT[Internal_Pin] = value;
227 Log.
w(ID,
"Unable to set Internal pin to int:", value);
228 Log.
w(ID,
"Pin:", Internal_Pin);
232 if (CAN_GPIO_MAP_OUT.find(Internal_Pin) != CAN_GPIO_MAP_OUT.end())
233 CAN_GPIO_MAP_OUT[Internal_Pin] = value;
237static int getOutgoingPinValue(uint8_t GPIO_Pin) {
239 return CAN_GPIO_MAP_OUT[GPIO_Pin];
245 if (CAN_GPIO_MAP_IN.find(CAN_GPIO_Pin) != CAN_GPIO_MAP_IN.end()) {
246 return *CAN_GPIO_MAP_IN[CAN_GPIO_Pin];
248 Log.
e(ID,
"Canpin was not defined before hand:", CAN_GPIO_Pin);
252 return *CAN_GPIO_MAP_IN[CAN_GPIO_Pin];
257 if (GPIO_Pin >= 100) {
259#define X(pin, Type, IO, init) __READPIN_##Type##IO(pin);
264 Log.
d(ID,
"No pin defined", GPIO_Pin);
271 if (GPIO_Pin >= 100) {
273#define X(pin, Type, IO, init) __WRITEPIN_##Type##IO(pin, value);
279 Log.
d(ID,
"No pin defined", GPIO_Pin);
290static void populateCanbusMap(std::multimap<uint32_t, std::tuple<uint, uint8_t, bool>> pinMap, analogCanPinMsg_t *analogCanPinStructArray, uint maxAnalogMsg, digitalCanPinMsg_t *digitalCanPinStruct, uint activeDigitalCanPinCount) {
293 decltype(pinMap.equal_range(0)) range;
294 for (
auto i = pinMap.begin(); i != pinMap.end(); i = range.second) {
295 range = pinMap.equal_range(i->first);
299 uint32_t address = i->first;
301 for (
auto d = range.first; d != range.second; ++d) {
302 if (std::get<2>(d->second)) {
303 if (amsgc == maxAnalogMsg) {
304 Log.
e(ID,
"Exceeded number of allocated analog canbus buffers, maximize the number of analog pins per address", amsgc);
308 Log.
w(ID,
"Address has too many analog pins allocated, ignoring additional pins", address);
311 analogCanPinStructArray[amsgc].address = address;
312 analogCanPinStructArray[amsgc].analogPinPos[ac] = std::get<0>(d->second);
313 analogCanPinStructArray[amsgc].analogPins[ac] = std::get<1>(d->second);
314 Log.
d(ID,
"", std::get<1>(d->second));
318 Log.
e(ID,
"Exceeded number of allocated digital canbus buffers, currently only one digital buffer is supported", dmsgc);
321 if (dc == activeDigitalCanPinCount) {
322 Log.
w(ID,
"Address has too many digital pins allocated, ignoring additional pins", address);
325 digitalCanPinStruct->address = address;
326 digitalCanPinStruct->digitalPinPos[dc] = std::get<0>(d->second);
327 digitalCanPinStruct->digitalPins[dc] = std::get<1>(d->second);
329 digitalCanPinStruct->activedigitalCanPins = dc;
336 Log.
i(ID,
"Set analog canbus buffer:", address);
340 Log.
i(ID,
"Set digital canbus buffer:", address);
341 for (
auto d = range.first; d != range.second; ++d) {
342 Log.
d(ID,
"", std::get<1>(d->second));
346 Log.
w(ID,
"No pins were set for address: ", address);
352#define X(pin, Type, IO, init) \
355 Log.d(ID, "Reset pin", pin); \
356 setPinValue(pin, init); \
363 canbusPinUpdate.end();
367 if (digitalCanPinCount_OUT + analogCanPinCount_OUT != 0) {
368 Log.
i(ID,
"Starting outgoing canpin update timer");
374 Log.
i(ID,
"Setting up physical pins");
380 Log.
i(ID,
"Setting up outgoing canbus pins");
381 std::multimap<uint32_t, std::tuple<uint, uint8_t, bool>> pinMap;
382 bool isAnalog =
true;
385#define X(address, pin) \
386 pinMap.insert(std::make_pair(address, std::make_tuple(i, pin, isAnalog))); \
387 CAN_GPIO_MAP_OUT[pin] = 0; \
394 Log.
i(ID,
"Populating outgoing messages");
395 populateCanbusMap(pinMap, analogCanPinMessages_OUT, analogCanMsgCount_OUT, &digitalCanPinMessage_OUT, digitalCanPinCount_OUT);
397 Log.
i(ID,
"Setting up incoming canbus pins");
402#define X(address, pin) \
403 pinMap.insert(std::make_pair(address, std::make_tuple(i, pin, isAnalog))); \
404 CAN_GPIO_MAP_IN[pin] = &CAN_GPIO_IN[i]; \
411 Log.
i(ID,
"Populating incoming messages");
412 populateCanbusMap(pinMap, analogCanPinMessages_IN, analogCanMsgCount_IN, &digitalCanPinMessage_IN, digitalCanPinCount_IN);
414 Log.
i(ID,
"Adding incoming canpin callbacks");
415 if (digitalCanPinCount_IN != 0)
416 Canbus::addCallback(digitalCanPinMessage_IN.address, _receiveDigitalCanbusPin);
417 for (
size_t i = 0; i < analogCanMsgCount_IN; i++) {
418 Canbus::addCallback(analogCanPinMessages_IN[i].address, _receiveAnalogCanbusPin);
423#ifdef CONF_LOGGING_ASCII_DEBUG
Configure global build properties.
Special logging functionality.
const char * LOG_TAG
Type definition of logging tags This typedef is necessary to allow for easier manipulation of code by...
Logging::Log_t Log
The global logging object.
#define PINS_CANBUS_DIGITAL_OUT
Same as PINS_CANBUS_DIGITAL_IN only for the digital pins that are outgoing.
#define CONF_PINS_CANBUS_UPDATE_INTERVAL_MICRO
The interval in micros to update outgoing canPins.
#define PINS_CANBUS_ANALOG_IN
The defintions of every analog pin to be received over canbus.
#define PINS_CANBUS_ANALOG_OUT
Same as PINS_CANBUS_ANALOG_IN only for the analog pins that are outgoing.
#define ECU_PINS
The defintions of every physical pin.
#define PINS_CANBUS_DIGITAL_IN
The defintions of every digital pin to be received over canbus.
Update, set, and get predefined pin values.
#define PINS_ANALOG_RES
The current target bit resolution of the ECU, set by PinConfig.def.
Get and set values to predefined pins.
void stopCanPins(void)
Stops background interrupts from sending canPins.
void setPinValue(uint8_t GPIO_Pin, int value)
Set the pin value of a predefined pin.
int getCanPinValue(uint8_t CAN_GPIO_Pin)
Get the pin value of a predefined canbus pin.
void initialize(void)
Initialize all predefined pins.
int getPinValue(uint8_t GPIO_Pin)
Get the pin value of a predefined pin.
void update(void)
Poll analog pin values.
void startCanPins(void)
Starts background interrupts to send canPins, if any are to be sent.
void setInternalValue(uint8_t Internal_Pin, int value)
Set the value of an internal pin.
void debugPrint(void)
Used for debugging.
void resetPhysicalPins()
Resets physical pins to their inital state.
void d(LOG_TAG TAG, LOG_MSG message)
Log a string using a debug tag.
void w(LOG_TAG TAG, LOG_MSG message)
Log a string using a warning tag.
void e(LOG_TAG TAG, LOG_MSG message)
Log a string using an error tag.
void i(LOG_TAG TAG, LOG_MSG message)
Log a string using an info tag.