Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: CANnucleo mbed ppCANOpen
Revision 10:ec59d628ebdc, committed 2016-03-19
- Comitter:
- ptpaterson
- Date:
- Sat Mar 19 01:44:35 2016 +0000
- Parent:
- 9:8352cfe17ab1
- Commit message:
- Final Submission (probs)
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Application/include/Node_pin0808.h Sat Mar 19 01:44:35 2016 +0000
@@ -0,0 +1,269 @@
+/**
+ ******************************************************************************
+ * @file
+ * @author Paul Paterson
+ * @version
+ * @date 2015-12-14
+ * @brief CANOpen implementation library
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>© COPYRIGHT(c) 2015 Paul Paterson
+ *
+ * All rights reserved.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef PPCAN_NODE_PIN0808_H
+#define PPCAN_NODE_PIN0808_H
+
+#include "Node.h"
+
+namespace ppCANOpen
+{
+
+/** Custom Object Dictionary for pinball io_0808 device.
+ */
+class Node_pin0808 : public Node
+{
+
+public:
+ Node_pin0808(int id, ServiceProvider * provider, int bLoop = 0);
+ virtual ~Node_pin0808(void);
+
+private:
+ /* constants */
+ /** milliseconds necessary to debounce all input */
+ static const uint8_t DEBOUNCE_TIME = 3;
+
+ /* IO details */
+ uint8_t prevInputBuffers[1];
+ uint8_t inputDebounce[8];
+
+ uint8_t prevOutputBuffers[1];
+ int scheduleIndexTime;
+
+ /**************************************************************************
+ * Implementation Overrides
+ **************************************************************************
+ */
+
+ /* Application run */
+ virtual void OnFixedUpdate(void);
+ virtual void OnUpdate(void);
+
+ /* SYNC */
+ virtual void OnSync (uint8_t counter);
+
+ /* NMT Control */
+ virtual void OnInitialize (void);
+ virtual void OnPreoperational (void);
+ virtual void OnOperational (void);
+ virtual void OnStopped (void);
+
+
+ /**************************************************************************
+ * Object Dictionary
+ **************************************************************************
+ */
+
+ /* Communication --------------------------------------------------------*/
+ /* index 0x1200 : SDO Server */
+ ObjectData Obj1200;
+ SubIndexSize Obj1200_highestSubIndex;
+ uint32_t Obj1200_ReceiveCobId;
+ uint32_t Obj1200_TransmitCobId;
+ EntryData Obj1200_entries[3];
+
+ /* index 0x1400 : Receive PDO 1 Parameter (Write Digital Output) */
+ ObjectData Obj1400;
+ SubIndexSize Obj1400_highestSubIndex;
+ uint32_t Obj1400_CobId;
+ uint8_t Obj1400_TransmissionType;
+ uint16_t Obj1400_InhibitTime;
+ uint8_t Obj1400_CompatibilityEntry;
+ uint16_t Obj1400_EventTimer;
+ EntryData Obj1400_entries[6];
+
+ /* index 0x1401 : Receive PDO 2 Parameter (Write Output Configuration) */
+ ObjectData Obj1401;
+ SubIndexSize Obj1401_highestSubIndex;
+ uint32_t Obj1401_CobId;
+ uint8_t Obj1401_TransmissionType;
+ uint16_t Obj1401_InhibitTime;
+ uint8_t Obj1401_CompatibilityEntry;
+ uint16_t Obj1401_EventTimer;
+ EntryData Obj1401_entries[6];
+
+ /* index 0x1402 : Receive PDO 3 Parameter (Write/Clear Autotrigger Rule) */
+ ObjectData Obj1402;
+ SubIndexSize Obj1402_highestSubIndex;
+ uint32_t Obj1402_CobId;
+ uint8_t Obj1402_TransmissionType;
+ uint16_t Obj1402_InhibitTime;
+ uint8_t Obj1402_CompatibilityEntry;
+ uint16_t Obj1402_EventTimer;
+ EntryData Obj1402_entries[6];
+
+ /* index 0x1403 : Receive PDO 5 Parameter (input changes) */
+ ObjectData Obj1403;
+ SubIndexSize Obj1403_highestSubIndex;
+ uint32_t Obj1403_CobId;
+ uint8_t Obj1403_TransmissionType;
+ uint16_t Obj1403_InhibitTime;
+ uint8_t Obj1403_CompatibilityEntry;
+ uint16_t Obj1403_EventTimer;
+ EntryData Obj1403_entries[6];
+
+ /* index 0x1600 : Receive PDO 1 Mapping */
+ ObjectData Obj1600;
+ SubIndexSize Obj1600_highestSubIndex;
+ uint32_t Obj1600_Map;
+ EntryData Obj1600_entries[2];
+
+ /* index 0x1601 : Transmit PDO 1 Mapping */
+ ObjectData Obj1601;
+ SubIndexSize Obj1601_highestSubIndex;
+ uint32_t Obj1601_Map;
+ EntryData Obj1601_entries[2];
+
+ /* index 0x1602 : Transmit PDO 1 Mapping */
+ ObjectData Obj1602;
+ SubIndexSize Obj1602_highestSubIndex;
+ uint32_t Obj1602_Map;
+ EntryData Obj1602_entries[2];
+
+ /* index 0x1603 : Receive PDO 2 Mapping */
+ ObjectData Obj1603;
+ SubIndexSize Obj1603_highestSubIndex;
+ uint32_t Obj1603_Map;
+ EntryData Obj1603_entries[2];
+
+
+ /* index 0x1800 : Transmit PDO 1 Parameter */
+ ObjectData Obj1800;
+ SubIndexSize Obj1800_highestSubIndex;
+ uint32_t Obj1800_CobId;
+ uint8_t Obj1800_TransmissionType;
+ uint16_t Obj1800_InhibitTime;
+ uint8_t Obj1800_CompatibilityEntry;
+ uint16_t Obj1800_EventTimer;
+ EntryData Obj1800_entries[6];
+
+ /* index 0x1A00 : Transmit PDO 1 Mapping */
+ ObjectData Obj1A00;
+ SubIndexSize Obj1A00_highestSubIndex;
+ uint32_t Obj1A00_MapInput;
+ uint32_t Obj1A00_MapVoid16;
+ uint32_t Obj1A00_MapChange;
+ uint32_t Obj1A00_MapSourceId;
+ EntryData Obj1A00_entries[6];
+
+
+ /* Manufacturer Specific ------------------------------------------------*/
+ /* index 0x2001 : Pin Output Configurations */
+ struct OutputConfiguration {
+ static const uint8_t PULSE = 0x01;
+ static const uint8_t PATTER = 0x02;
+ static const uint8_t PULSED_PATTER = 0x04;
+ //static const uint8_t SCHEDULED = 0x08;
+
+ uint8_t type;
+ uint8_t pulse_ms;
+ uint8_t pwm_on;
+ uint8_t pwm_off;
+ uint32_t writeData;
+ };
+
+ ObjectData Obj2001;
+ SubIndexSize Obj2001_highestSubIndex;
+ OutputConfiguration writeOutputConfig;
+ OutputConfiguration outputConfigs[8];
+ OutputConfiguration outputTimers[8]; /* not actually part of dictionary */
+ EntryData Obj2001_entries[10];
+
+ /* index 0x2002 : Output Schedule Configuration */
+ ObjectData Obj2002;
+ SubIndexSize Obj2002_highestSubIndex;
+ uint32_t scheduleConfig;
+ uint32_t schedules[8];
+ EntryData Obj2002_entries[10];
+
+ /* index 0x2100 : Input change data */
+ ObjectData Obj2100;
+ SubIndexSize Obj2100_highestSubIndex;
+ uint8_t inputChangeMask[1];
+ /* uint8_t nodeId; */
+ EntryData Obj2100_entries[3];
+
+ /* index 0x2200 : Autotrigger Rules */
+ struct AutotriggerRule {
+ uint8_t sourceId;
+ uint8_t input; /* 0-4: inputNum (0-23)
+ 5-7: 0 on inactive
+ 1 on active
+ 2 on any change
+ 3 ???
+ */
+ uint8_t setMask[3];
+ uint8_t clearMask[3];
+ };
+
+ struct AutotriggerMessage {
+ uint8_t input[3];
+ uint8_t change[3];
+ uint8_t sourceId;
+ };
+
+ ObjectData Obj2200;
+ SubIndexSize Obj2200_highestSubIndex;
+ AutotriggerRule writeRule;
+ AutotriggerMessage autotriggerMessage;
+ AutotriggerRule rules[24];
+ EntryData Obj2200_entries[27];
+
+
+ /* Device Specific ------------------------------------------------------*/
+ /* index 0x6000 : Mapped variable "inputs" */
+ ObjectData Obj6000;
+ SubIndexSize Obj6000_highestSubIndex;
+ uint8_t readInputBuffers[1];
+ EntryData Obj6000_entries[2];
+
+ /* index 0x6005 : Global Input Interrupt Enable */
+ ObjectData Obj6005;
+ SubIndexSize Obj6005_highestSubIndex;
+ uint8_t bInputInterruptEnable;
+ EntryData Obj6005_entries[2];
+
+ /* index 0x6006 : Any Change Interrupt Mask */
+ ObjectData Obj6006;
+ SubIndexSize Obj6006_highestSubIndex;
+ uint8_t inputInterruptMask[1];
+ EntryData Obj6006_entries[2];
+
+ /* index 0x6200 : Mapped variable "outputs" */
+ ObjectData Obj6200;
+ SubIndexSize Obj6200_highestSubIndex;
+ uint8_t writeOutputBuffers[1];
+ EntryData Obj6200_entries[2];
+
+ /* Scan Method */
+ virtual ObjectData * ScanIndex(IndexSize index);
+};
+
+} /* namespace ppCANOpen */
+
+#endif // PPCAN_NODE_PIN0808_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Application/include/SerialBuffered.h Sat Mar 19 01:44:35 2016 +0000
@@ -0,0 +1,61 @@
+#ifndef _SERIAL_BUFFERED_H_
+#define _SERIAL_BUFFERED_H_
+
+/**
+ * Buffered serial class.
+ */
+class SerialBuffered : public Serial {
+public:
+ /**
+ * Create a buffered serial class.
+ *
+ * @param tx A pin for transmit.
+ * @param rx A pin for receive.
+ */
+ SerialBuffered(PinName tx, PinName rx);
+
+ /**
+ * Destroy.
+ */
+ virtual ~SerialBuffered();
+
+ /**
+ * Get a character.
+ *
+ * @return A character. (-1:timeout)
+ */
+ int getc();
+
+ /**
+ * Returns 1 if there is a character available to read, 0 otherwise.
+ */
+ int readable();
+
+ /**
+ * Set timeout for getc().
+ *
+ * @param ms milliseconds. (-1:Disable timeout)
+ */
+ void setTimeout(int ms);
+
+ /**
+ * Read requested bytes.
+ *
+ * @param bytes A pointer to a buffer.
+ * @param requested Length.
+ *
+ * @return Readed byte length.
+ */
+ size_t readBytes(uint8_t *bytes, size_t requested);
+
+private:
+ void handleInterrupt();
+ static const int BUFFERSIZE = 2048;
+ uint8_t buffer[BUFFERSIZE]; // points at a circular buffer, containing data from m_contentStart, for m_contentSize bytes, wrapping when you get to the end
+ uint16_t indexContentStart; // index of first bytes of content
+ uint16_t indexContentEnd; // index of bytes after last byte of content
+ int timeout;
+ Timer timer;
+};
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Application/source/Node_pin0808.cpp Sat Mar 19 01:44:35 2016 +0000
@@ -0,0 +1,700 @@
+/**
+ ******************************************************************************
+ * @file
+ * @author Paul Paterson
+ * @version
+ * @date 2015-12-14
+ * @brief CANOpen implementation library
+ ******************************************************************************
+ * @attention
+ *
+ * <h2><center>© COPYRIGHT(c) 2015 Paul Paterson
+ *
+ * All rights reserved.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "Node_pin0808.h"
+#include "ServiceProvider.h"
+
+#include "stdio.h"
+#include "mbed.h"
+
+PortIn mbedInputs(PortB, 0x00FF);
+PortOut mbedOutputs(PortB, 0xFF00);
+
+namespace ppCANOpen
+{
+
+/******************************************************************************
+ * Constructor/Destructor
+ ******************************************************************************
+ */
+
+Node_pin0808::Node_pin0808 (int id, ServiceProvider * provider, int bLoop)
+ : Node(id, provider, bLoop)
+{
+ dictionary = new ObjectData[22];
+
+
+ /* Init values ***********************************************************/
+ memset(prevInputBuffers, 0, sizeof(prevInputBuffers));
+ memset(inputDebounce, 0, sizeof(inputDebounce));
+
+ memset(prevOutputBuffers,0, sizeof(prevOutputBuffers));
+
+ /* Init Object Dictionary ************************************************/
+
+ /* Communication Objects ================================================*/
+
+ /* SDO ------------------------------------------------------------------*/
+ /* index 0x1200 */
+ Obj1200_highestSubIndex = 2;
+ Obj1200_ReceiveCobId = 0x600 + nodeId;
+ Obj1200_TransmitCobId = 0x580 + nodeId;
+ Obj1200_entries[0] = EntryData((void*)&Obj1200_highestSubIndex, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
+ Obj1200_entries[1] = EntryData((void*)&Obj1200_ReceiveCobId, sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj1200_entries[2] = EntryData((void*)&Obj1200_TransmitCobId, sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj1200 = ObjectData(Obj1200_entries, 0x1200, sizeof(Obj1200_entries) / sizeof(Obj1200_entries[0]));
+
+ /* RPDO -----------------------------------------------------------------*/
+ /* index 0x1400 */
+ Obj1400_highestSubIndex = 5;
+ Obj1400_CobId = 0x200 + nodeId;
+ Obj1400_TransmissionType = 1;
+ Obj1400_InhibitTime = 0;
+ Obj1400_CompatibilityEntry = 0;
+ Obj1400_EventTimer = 0;
+ Obj1400_entries[0] = EntryData((void*)&Obj1400_highestSubIndex, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
+ Obj1400_entries[1] = EntryData((void*)&Obj1400_CobId, sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj1400_entries[2] = EntryData((void*)&Obj1400_TransmissionType, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
+ Obj1400_entries[3] = EntryData((void*)&Obj1400_InhibitTime, sizeof(uint16_t), EntryData::TYPE_UINT16, EntryData::PROPERTY_READABLE);
+ Obj1400_entries[4] = EntryData((void*)&Obj1400_CompatibilityEntry, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
+ Obj1400_entries[5] = EntryData((void*)&Obj1400_EventTimer, sizeof(uint16_t), EntryData::TYPE_UINT16, EntryData::PROPERTY_READABLE);
+ Obj1400 = ObjectData(Obj1400_entries, 0x1400, sizeof(Obj1400_entries) / sizeof(Obj1400_entries[0]));
+
+ /* index 0x1401 */
+ Obj1401_highestSubIndex = 5;
+ Obj1401_CobId = 0x300 + nodeId;
+ Obj1401_TransmissionType = 1;
+ Obj1401_InhibitTime = 0;
+ Obj1401_CompatibilityEntry = 0;
+ Obj1401_EventTimer = 0;
+ Obj1401_entries[0] = EntryData((void*)&Obj1401_highestSubIndex, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
+ Obj1401_entries[1] = EntryData((void*)&Obj1401_CobId, sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj1401_entries[2] = EntryData((void*)&Obj1401_TransmissionType, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
+ Obj1401_entries[3] = EntryData((void*)&Obj1401_InhibitTime, sizeof(uint16_t), EntryData::TYPE_UINT16, EntryData::PROPERTY_READABLE);
+ Obj1401_entries[4] = EntryData((void*)&Obj1401_CompatibilityEntry, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
+ Obj1401_entries[5] = EntryData((void*)&Obj1401_EventTimer, sizeof(uint16_t), EntryData::TYPE_UINT16, EntryData::PROPERTY_READABLE);
+ Obj1401 = ObjectData(Obj1401_entries, 0x1401, sizeof(Obj1401_entries) / sizeof(Obj1401_entries[0]));
+
+ /* index 0x1402 */
+ Obj1402_highestSubIndex = 5;
+ Obj1402_CobId = 0x400 + nodeId;
+ Obj1402_TransmissionType = 1;
+ Obj1402_InhibitTime = 0;
+ Obj1402_CompatibilityEntry = 0;
+ Obj1402_EventTimer = 0;
+ Obj1402_entries[0] = EntryData((void*)&Obj1402_highestSubIndex, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
+ Obj1402_entries[1] = EntryData((void*)&Obj1402_CobId, sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj1402_entries[2] = EntryData((void*)&Obj1402_TransmissionType, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
+ Obj1402_entries[3] = EntryData((void*)&Obj1402_InhibitTime, sizeof(uint16_t), EntryData::TYPE_UINT16, EntryData::PROPERTY_READABLE);
+ Obj1402_entries[4] = EntryData((void*)&Obj1402_CompatibilityEntry, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
+ Obj1402_entries[5] = EntryData((void*)&Obj1402_EventTimer, sizeof(uint16_t), EntryData::TYPE_UINT16, EntryData::PROPERTY_READABLE);
+ Obj1402 = ObjectData(Obj1402_entries, 0x1402, sizeof(Obj1402_entries) / sizeof(Obj1402_entries[0]));
+
+ /* index 0x1403 */
+ Obj1403_highestSubIndex = 5;
+ Obj1403_CobId = 0x181;
+ Obj1403_TransmissionType = 1;
+ Obj1403_InhibitTime = 0;
+ Obj1403_CompatibilityEntry = 0;
+ Obj1403_EventTimer = 0;
+ Obj1403_entries[0] = EntryData((void*)&Obj1403_highestSubIndex, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
+ Obj1403_entries[1] = EntryData((void*)&Obj1403_CobId, sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj1403_entries[2] = EntryData((void*)&Obj1403_TransmissionType, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
+ Obj1403_entries[3] = EntryData((void*)&Obj1403_InhibitTime, sizeof(uint16_t), EntryData::TYPE_UINT16, EntryData::PROPERTY_READABLE);
+ Obj1403_entries[4] = EntryData((void*)&Obj1403_CompatibilityEntry, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
+ Obj1403_entries[5] = EntryData((void*)&Obj1403_EventTimer, sizeof(uint16_t), EntryData::TYPE_UINT16, EntryData::PROPERTY_READABLE);
+ Obj1403 = ObjectData(Obj1403_entries, 0x1403, sizeof(Obj1403_entries) / sizeof(Obj1403_entries[0]));
+
+ /* index 0x1600 */
+ Obj1600_highestSubIndex = 1;
+ Obj1600_Map = 0x62000108;
+ Obj1600_entries[0] = EntryData((void*)&Obj1600_highestSubIndex, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
+ Obj1600_entries[1] = EntryData((void*)&Obj1600_Map, sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj1600 = ObjectData(Obj1600_entries, 0x1600, sizeof(Obj1600_entries) / sizeof(Obj1600_entries[0]));
+
+ /* index 0x1601 */
+ Obj1601_highestSubIndex = 1;
+ Obj1601_Map = 0x20010140;
+ Obj1601_entries[0] = EntryData((void*)&Obj1601_highestSubIndex, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
+ Obj1601_entries[1] = EntryData((void*)&Obj1601_Map, sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj1601 = ObjectData(Obj1601_entries, 0x1601, sizeof(Obj1601_entries) / sizeof(Obj1601_entries[0]));
+
+ /* index 0x1602 */
+ Obj1602_highestSubIndex = 1;
+ Obj1602_Map = 0x22000140;
+ Obj1602_entries[0] = EntryData((void*)&Obj1602_highestSubIndex, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
+ Obj1602_entries[1] = EntryData((void*)&Obj1602_Map, sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj1602 = ObjectData(Obj1602_entries, 0x1602, sizeof(Obj1602_entries) / sizeof(Obj1602_entries[0]));
+
+ /* index 0x1603 */
+ Obj1603_highestSubIndex = 1;
+ Obj1603_Map = 0x22000238;
+ Obj1603_entries[0] = EntryData((void*)&Obj1603_highestSubIndex, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
+ Obj1603_entries[1] = EntryData((void*)&Obj1603_Map, sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj1603 = ObjectData(Obj1603_entries, 0x1603, sizeof(Obj1603_entries) / sizeof(Obj1603_entries[0]));
+
+ /* TPDO -----------------------------------------------------------------*/
+ /* index 0x1800 */
+ Obj1800_highestSubIndex = 5;
+ Obj1800_CobId = 0x181;
+ Obj1800_TransmissionType = 0xFE; /* event driven Manuf specific */
+ Obj1800_InhibitTime = 0; // TODO review if this is needed
+ Obj1800_CompatibilityEntry = 0;
+ Obj1800_EventTimer = 0;
+ Obj1800_entries[0] = EntryData((void*)&Obj1800_highestSubIndex, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
+ Obj1800_entries[1] = EntryData((void*)&Obj1800_CobId, sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj1800_entries[2] = EntryData((void*)&Obj1800_TransmissionType, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
+ Obj1800_entries[3] = EntryData((void*)&Obj1800_InhibitTime, sizeof(uint16_t), EntryData::TYPE_UINT16, EntryData::PROPERTY_READABLE);
+ Obj1800_entries[4] = EntryData((void*)&Obj1800_CompatibilityEntry, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
+ Obj1800_entries[5] = EntryData((void*)&Obj1800_EventTimer, sizeof(uint16_t), EntryData::TYPE_UINT16, EntryData::PROPERTY_READABLE);
+ Obj1800 = ObjectData(Obj1800_entries, 0x1800, sizeof(Obj1800_entries) / sizeof(Obj1800_entries[0]));
+
+ /* index 0x1A00 */
+ Obj1A00_highestSubIndex = 5;
+ Obj1A00_MapInput = 0x60000108;
+ Obj1A00_MapVoid16 = 0x00000010;
+ Obj1A00_MapChange = 0x21000108;
+ Obj1A00_MapSourceId = 0x21000208;
+ Obj1A00_entries[0] = EntryData((void*)&Obj1A00_highestSubIndex, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
+ Obj1A00_entries[1] = EntryData((void*)&Obj1A00_MapInput, sizeof(uint8_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj1A00_entries[2] = EntryData((void*)&Obj1A00_MapVoid16, sizeof(uint16_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj1A00_entries[3] = EntryData((void*)&Obj1A00_MapChange, sizeof(uint8_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj1A00_entries[4] = EntryData((void*)&Obj1A00_MapVoid16, sizeof(uint16_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj1A00_entries[5] = EntryData((void*)&Obj1A00_MapSourceId, sizeof(uint8_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj1A00 = ObjectData(Obj1A00_entries, 0x1A00, sizeof(Obj1A00_entries) / sizeof(Obj1A00_entries[0]));
+
+
+ /* Manufacturer Specific Objects ========================================*/
+
+ /* index 0x2001 : Pin Output Configurations */
+ Obj2001_highestSubIndex = 8;
+ memset(&writeOutputConfig, 0, sizeof(writeOutputConfig));
+ memset(outputConfigs, 0, sizeof(outputConfigs));
+ outputConfigs[0].type = 0x08;
+ memset(outputTimers, 0, sizeof(outputTimers));
+ Obj2001_entries[0] = EntryData((void*)&Obj2001_highestSubIndex, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
+ Obj2001_entries[1] = EntryData((void*)&writeOutputConfig, sizeof(OutputConfiguration), EntryData::TYPE_UINT64, EntryData::PROPERTY_READ_WRITEABLE);
+ Obj2001_entries[2] = EntryData((void*)&outputConfigs[0], sizeof(OutputConfiguration), EntryData::TYPE_UINT64, EntryData::PROPERTY_READ_WRITEABLE);
+ Obj2001_entries[3] = EntryData((void*)&outputConfigs[1], sizeof(OutputConfiguration), EntryData::TYPE_UINT64, EntryData::PROPERTY_READ_WRITEABLE);
+ Obj2001_entries[4] = EntryData((void*)&outputConfigs[2], sizeof(OutputConfiguration), EntryData::TYPE_UINT64, EntryData::PROPERTY_READ_WRITEABLE);
+ Obj2001_entries[5] = EntryData((void*)&outputConfigs[3], sizeof(OutputConfiguration), EntryData::TYPE_UINT64, EntryData::PROPERTY_READ_WRITEABLE);
+ Obj2001_entries[6] = EntryData((void*)&outputConfigs[4], sizeof(OutputConfiguration), EntryData::TYPE_UINT64, EntryData::PROPERTY_READ_WRITEABLE);
+ Obj2001_entries[7] = EntryData((void*)&outputConfigs[5], sizeof(OutputConfiguration), EntryData::TYPE_UINT64, EntryData::PROPERTY_READ_WRITEABLE);
+ Obj2001_entries[8] = EntryData((void*)&outputConfigs[6], sizeof(OutputConfiguration), EntryData::TYPE_UINT64, EntryData::PROPERTY_READ_WRITEABLE);
+ Obj2001_entries[9] = EntryData((void*)&outputConfigs[7], sizeof(OutputConfiguration), EntryData::TYPE_UINT64, EntryData::PROPERTY_READ_WRITEABLE);
+ Obj2001 = ObjectData(Obj2001_entries, 0x2001, sizeof(Obj2001_entries) / sizeof(Obj2001_entries[0]));
+
+ /* index 0x2002 : Output Schedule Configuration */
+ Obj2002_highestSubIndex = 1;
+ scheduleConfig = 0x01;
+ schedules[0] = 0xFF00F0F0;
+ Obj2002_entries[0] = EntryData((void*)&Obj2002_highestSubIndex, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
+ Obj2002_entries[1] = EntryData((void*)&scheduleConfig, sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READ_WRITEABLE);
+ Obj2002_entries[2] = EntryData((void*)&schedules[0], sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READ_WRITEABLE);
+ Obj2002_entries[3] = EntryData((void*)&schedules[1], sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READ_WRITEABLE);
+ Obj2002_entries[4] = EntryData((void*)&schedules[2], sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READ_WRITEABLE);
+ Obj2002_entries[5] = EntryData((void*)&schedules[3], sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READ_WRITEABLE);
+ Obj2002_entries[6] = EntryData((void*)&schedules[4], sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READ_WRITEABLE);
+ Obj2002_entries[7] = EntryData((void*)&schedules[5], sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READ_WRITEABLE);
+ Obj2002_entries[8] = EntryData((void*)&schedules[6], sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READ_WRITEABLE);
+ Obj2002_entries[9] = EntryData((void*)&schedules[7], sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READ_WRITEABLE);
+ Obj2002 = ObjectData(Obj2002_entries, 0x2002, sizeof(Obj2002_entries) / sizeof(Obj2002_entries[0]));
+
+ /* Index 2100 */
+ Obj2100_highestSubIndex = 2;
+ inputChangeMask[0] = 0;
+ /* nodeId; */
+ Obj2100_entries[0] = EntryData((void*)&Obj2100_highestSubIndex, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
+ Obj2100_entries[1] = EntryData((void*)&inputChangeMask[0], sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
+ Obj2100_entries[2] = EntryData((void*)&nodeId, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
+ Obj2100 = ObjectData(Obj2100_entries, 0x2100, sizeof(Obj2100_entries) / sizeof(Obj2100_entries[0]));
+
+ /* Index 2200 */
+ Obj2200_highestSubIndex = 2;
+ memset(&writeRule, 0, sizeof(AutotriggerRule));
+ memset(&autotriggerMessage, 0, sizeof(AutotriggerMessage));
+ memset(rules, 0, sizeof(rules));
+ Obj2200_entries[0] = EntryData((void*)&Obj2200_highestSubIndex, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
+ Obj2200_entries[1] = EntryData((void*)&writeRule, sizeof(AutotriggerRule), EntryData::TYPE_UINT32, EntryData::PROPERTY_READ_WRITEABLE);
+ Obj2200_entries[2] = EntryData((void*)&autotriggerMessage, sizeof(AutotriggerMessage), EntryData::TYPE_UINT32, EntryData::PROPERTY_READ_WRITEABLE);
+ Obj2200_entries[3] = EntryData((void*)&rules[0], sizeof(AutotriggerRule), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj2200_entries[4] = EntryData((void*)&rules[1], sizeof(AutotriggerRule), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj2200_entries[5] = EntryData((void*)&rules[2], sizeof(AutotriggerRule), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj2200_entries[6] = EntryData((void*)&rules[3], sizeof(AutotriggerRule), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj2200_entries[7] = EntryData((void*)&rules[4], sizeof(AutotriggerRule), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj2200_entries[8] = EntryData((void*)&rules[5], sizeof(AutotriggerRule), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj2200_entries[9] = EntryData((void*)&rules[6], sizeof(AutotriggerRule), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj2200_entries[10] = EntryData((void*)&rules[7], sizeof(AutotriggerRule), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj2200_entries[11] = EntryData((void*)&rules[8], sizeof(AutotriggerRule), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj2200_entries[12] = EntryData((void*)&rules[9], sizeof(AutotriggerRule), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj2200_entries[13] = EntryData((void*)&rules[10], sizeof(AutotriggerRule), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj2200_entries[14] = EntryData((void*)&rules[11], sizeof(AutotriggerRule), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj2200_entries[15] = EntryData((void*)&rules[12], sizeof(AutotriggerRule), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj2200_entries[16] = EntryData((void*)&rules[13], sizeof(AutotriggerRule), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj2200_entries[17] = EntryData((void*)&rules[14], sizeof(AutotriggerRule), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj2200_entries[18] = EntryData((void*)&rules[15], sizeof(AutotriggerRule), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj2200_entries[19] = EntryData((void*)&rules[16], sizeof(AutotriggerRule), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj2200_entries[20] = EntryData((void*)&rules[17], sizeof(AutotriggerRule), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj2200_entries[21] = EntryData((void*)&rules[18], sizeof(AutotriggerRule), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj2200_entries[22] = EntryData((void*)&rules[19], sizeof(AutotriggerRule), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj2200_entries[23] = EntryData((void*)&rules[20], sizeof(AutotriggerRule), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj2200_entries[24] = EntryData((void*)&rules[21], sizeof(AutotriggerRule), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj2200_entries[25] = EntryData((void*)&rules[22], sizeof(AutotriggerRule), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj2200_entries[26] = EntryData((void*)&rules[23], sizeof(AutotriggerRule), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
+ Obj2200 = ObjectData(Obj2200_entries, 0x2200, sizeof(Obj2200_entries) / sizeof(Obj2200_entries[0]));
+
+ /* Device Profile Specific Objects ======================================*/
+
+ /* Index 6000 */
+ Obj6000_highestSubIndex = 1;
+ readInputBuffers[0] = 0;
+ Obj6000_entries[0] = EntryData((void*)&Obj6000_highestSubIndex, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
+ Obj6000_entries[1] = EntryData((void*)&readInputBuffers, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
+ Obj6000 = ObjectData(Obj6000_entries, 0x6000, sizeof(Obj6000_entries) / sizeof(Obj6000_entries[0]));
+
+ /* Index 6005 */
+ Obj6005_highestSubIndex = 1;
+ bInputInterruptEnable = 0x01;
+ Obj6005_entries[0] = EntryData((void*)&Obj6005_highestSubIndex, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
+ Obj6005_entries[1] = EntryData((void*)&bInputInterruptEnable, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READ_WRITEABLE);
+ Obj6005 = ObjectData(Obj6005_entries, 0x6005, sizeof(Obj6005_entries) / sizeof(Obj6005_entries[0]));
+
+ /* Index 6006 */
+ Obj6006_highestSubIndex = 1;
+ inputInterruptMask[0] = 0xFF;
+ Obj6006_entries[0] = EntryData((void*)&Obj6006_highestSubIndex, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
+ Obj6006_entries[1] = EntryData((void*)&inputInterruptMask, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READ_WRITEABLE);
+ Obj6006 = ObjectData(Obj6006_entries, 0x6006, sizeof(Obj6006_entries) / sizeof(Obj6006_entries[0]));
+
+ /* Index 6200 */
+ Obj6200_highestSubIndex = 1;
+ writeOutputBuffers[0] = 0;
+ Obj6200_entries[0] = EntryData((void*)&Obj6200_highestSubIndex, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
+ Obj6200_entries[1] = EntryData((void*)&writeOutputBuffers, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READ_WRITEABLE);
+ Obj6200 = ObjectData(Obj6200_entries, 0x6200, sizeof(Obj6200_entries) / sizeof(Obj6200_entries[0]));
+
+ /* Set up the whole dictionary */
+ dictionary[0] = Obj1200;
+ dictionary[1] = Obj1400;
+ dictionary[2] = Obj1401;
+ dictionary[3] = Obj1402;
+ dictionary[4] = Obj1403;
+ dictionary[5] = Obj1600;
+ dictionary[6] = Obj1601;
+ dictionary[7] = Obj1602;
+ dictionary[8] = Obj1603;
+ dictionary[10] = Obj1800;
+ dictionary[11] = Obj1A00;
+ dictionary[12] = Obj2001;
+ dictionary[13] = Obj2002;
+ dictionary[14] = Obj2100;
+ dictionary[15] = Obj2200;
+ dictionary[16] = Obj6000;
+ dictionary[17] = Obj6005;
+ dictionary[18] = Obj6006;
+ dictionary[19] = Obj6200;
+
+}
+
+Node_pin0808::~Node_pin0808(void)
+{
+ delete dictionary;
+}
+
+/******************************************************************************
+ * Application Run Implementation
+ ******************************************************************************
+ */
+
+void Node_pin0808::OnFixedUpdate (void)
+{
+ /**************************************************************************
+ * INPUTS
+ **************************************************************************
+ */
+
+ uint8_t inputSample = ~(uint8_t)(mbedInputs.read());
+
+ uint8_t inputChange = readInputBuffers[0] ^ inputSample;
+
+ /* Loop through all of the inputs */
+ for (int in = 0; in < 8; in++) {
+ if (inputChange & (1 << in)) {
+
+ inputDebounce[in] += (uint8_t)(timeSinceLastTick);
+ if (inputDebounce[in] > DEBOUNCE_TIME) {
+ readInputBuffers[0] &= ~(1 << in);
+ readInputBuffers[0] |= (inputSample & (1 << in));
+
+ inputDebounce[in] = 0;
+ }
+
+ } else {
+ inputDebounce[in] = 0;
+ }
+ }
+
+
+ /**************************************************************************
+ * OUTPUTS
+ **************************************************************************
+ */
+
+ /* create a copy of the current outputs and edit as we go */
+ uint8_t newOutput = (uint8_t)(mbedOutputs >> 8);
+
+ /* big operation, so let's only do it once! */
+ int scheduleIndexer = 1 << ((timeCurrentTick * 100) / 3125) % 32;
+
+ /* Loop through all of the outputs */
+ for (int out = 0; out < 8; out++) {
+
+ if (scheduleConfig & (1 << out)) {
+
+ if (schedules[out] & scheduleIndexer) {
+ writeOutputBuffers[0] |= (1 << out);
+ } else {
+ writeOutputBuffers[0] &= ~(1 << out);
+ }
+ }
+
+ /* update GPIO's immediately only if new signal was given */
+ int outputBufferChanges = writeOutputBuffers[0] ^ prevOutputBuffers[0];
+
+ if (outputBufferChanges & (1 << out)) {
+ if ((1 << out) & writeOutputBuffers[0]) {
+ /* switched on */
+ newOutput |= (1 << out);
+
+ /* reset timers */
+ if (outputConfigs[out].type) {
+ outputTimers[out] = OutputConfiguration(outputConfigs[out]);
+ }
+ } else {
+ /* switched off */
+ newOutput &= ~(1 << out);
+ memset(&outputTimers[out], 0, sizeof(outputTimers[out]));
+ }
+ }
+
+ /* if there is a pulse run down the timer */
+ if (outputTimers[out].type & 0x01) {
+
+ if (outputTimers[out].pulse_ms >= timeSinceLastTick) {
+ outputTimers[out].pulse_ms -= timeSinceLastTick;
+ } else {
+ /* time past would put timer below 0 */
+ outputTimers[out].pulse_ms = 0;
+ }
+
+ /* if time has run out */
+ if (0 == outputTimers[out].pulse_ms) {
+
+ /* just turn off pulse */
+ outputTimers[out].type &= 0xFE;
+ newOutput &= ~(1 << out);
+
+ /* if there is a patter, then output buffer will stay on */
+ /* but if there is a pulsed-patter, then it should still turn off */
+ if (!(outputTimers[out].type & 0x02) ||
+ (outputTimers[out].type & (0x02 | 0x04))) {
+ /* turn buffer off */
+ outputTimers[out].type = 0;
+ writeOutputBuffers[0] &= ~(1 << out);
+ }
+ }
+ }
+
+ /* two ways to patter:
+ * wait until after pulse (pulse-then-patter),
+ * or config so pulse happens at same time (pulsed-patter)
+ */
+ if (((outputTimers[out].type & 0x02) && !(outputTimers[out].type & 0x01)) ||
+ ((outputTimers[out].type & (0x02 | 0x04)) && (outputTimers[out].type & 0x01))) {
+
+ /* if output is on, run down pwm_on, else tun down pwm_off */
+ uint8_t *pw_timer;
+ if (newOutput & (1 << out)) {
+ pw_timer = &outputTimers[out].pwm_on;
+ } else {
+ pw_timer = &outputTimers[out].pwm_off;
+ }
+
+ if (*pw_timer >= timeSinceLastTick) {
+ *pw_timer -= timeSinceLastTick;
+ } else {
+ *pw_timer = 0;
+ }
+
+ if (*pw_timer == 0) {
+ newOutput ^= (1 << out);
+
+ outputTimers[out].pwm_on = outputConfigs[out].pwm_on;
+ outputTimers[out].pwm_off = outputConfigs[out].pwm_off;
+ }
+ }
+
+
+ }
+
+ mbedOutputs = ((uint16_t)newOutput) << 8;
+
+ prevOutputBuffers[0] = writeOutputBuffers[0];
+}
+
+void Node_pin0808::OnUpdate (void)
+{
+ /* Check for output configurations --------------------------------------*/
+ if (writeOutputConfig.writeData) {
+ uint8_t out = (uint8_t)(writeOutputConfig.writeData);
+
+ writeOutputConfig.writeData = 0;
+ outputConfigs[out] = writeOutputConfig;
+
+ memset(&writeOutputConfig, 0, sizeof(writeOutputConfig));
+ }
+
+
+ /* Check for rule configurations ----------------------------------------*/
+ if (writeRule.sourceId) {
+ printf(" Configuring Rules...\r\n");
+ if (writeRule.sourceId & 0x80) {
+ /* write new rule*/
+
+ /* scan through array of rules for available (8th bit cleared) */
+ int ruleNum = 0;
+ while (ruleNum < 24) {
+ if (!(rules[ruleNum].sourceId & 0x80)) {
+
+ rules[ruleNum] = writeRule;
+ printf(" Rule added: #%d\r\n", ruleNum);
+ ruleNum = 24;
+ } else {
+ ruleNum++;
+ if (ruleNum == 24) {
+ printf(" ERROR: Not enough rules available");
+ }
+ }
+ }
+
+ } else {
+ /* clear rules */
+
+ /* scan through array of rules matching input and disable */
+ for (int ruleNum = 0; ruleNum < 24; ruleNum++) {
+
+ /* check if rule enabled and input num matches */
+ if ((rules[ruleNum].sourceId & 0x80) &&
+ ((rules[ruleNum].sourceId & 0x7F) == writeRule.sourceId) &&
+ ((rules[ruleNum].input & 0x1F) == (writeRule.input & 0x1F)))
+ {
+ memset(&rules[ruleNum], 0, sizeof(AutotriggerRule));
+ printf(" Rule removed: #%d\r\n", ruleNum);
+ }
+
+ }
+ }
+
+ memset(&writeRule, 0, sizeof(AutotriggerRule));
+ }
+
+ /* check for input changes from other devices---------------------------*/
+ if (autotriggerMessage.sourceId) {
+
+ printf(" detected change from node: %#04x\r\n", (autotriggerMessage.sourceId & 0x7F));
+ /* scan through array of rules matching inputs and direction */
+ for (int ruleNum = 0; ruleNum < 24; ruleNum++) {
+
+ /* check if rule enabled and input num matches */
+ if ((rules[ruleNum].sourceId & 0x80) && /* rule is active AND */
+ (rules[ruleNum].sourceId == autotriggerMessage.sourceId) && /* rule source matches message source AND */
+ (autotriggerMessage.change[0] & (1 << (rules[ruleNum].input & 0x1F)))) /* change exists at input num */
+ {
+
+ int ruleActivity = rules[ruleNum].input >> 5;
+ int inputActivity = (autotriggerMessage.input[0] >> (rules[ruleNum].input & 0x1F)) & 1;
+
+ printf(" id match: %#04x\r\n", ruleNum);
+ printf(" ruleActivity: %#04x\r\n", ruleActivity);
+ printf(" inputActivity: %#04x\r\n", inputActivity);
+
+ if ((2 == ruleActivity) || (inputActivity == ruleActivity)) {
+
+ printf(" activating Rule...\r\n");
+ printf(" setMask: %#10x\r\n", rules[ruleNum].setMask[0]);
+ printf(" clearMask: %#10x\r\n", ~rules[ruleNum].clearMask[0]);
+
+ writeOutputBuffers[0] |= rules[ruleNum].setMask[0];
+ //writeOutputBuffers[1] |= rules[ruleNum].setMask[1];
+ //writeOutputBuffers[2] |= rules[ruleNum].setMask[2];
+
+ writeOutputBuffers[0] &= ~rules[ruleNum].clearMask[0];
+ //writeOutputBuffers[1] &= ~rules[ruleNum].clearMask[1];
+ //writeOutputBuffers[2] &= ~rules[ruleNum].clearMask[2];
+ }
+ }
+
+ }
+
+ memset(&autotriggerMessage, 0, sizeof(AutotriggerMessage));
+ }
+
+ /* check for input changes from this device -----------------------------*/
+ /* update Index 2101-01 */
+ inputChangeMask[0] = readInputBuffers[0] ^ prevInputBuffers[0];
+
+ /* check for rules against this devices inputs */
+ if (inputChangeMask[0]) {
+ /* scan through array of rules matching inputs and direction */
+ for (int ruleNum = 0; ruleNum < 24; ruleNum++) {
+
+ /* check if rule enabled and input num matches */
+ if ((rules[ruleNum].sourceId & 0x80) && /* rule is active AND */
+ ((rules[ruleNum].sourceId & 0x7F) == nodeId) && /* rule source is this nodeId AND */
+ (inputChangeMask[0] & (1 << (rules[ruleNum].input & 0x1F)))) /* change exists at input num */
+ {
+
+ int ruleActivity = rules[ruleNum].input >> 5;
+ int inputActivity = (readInputBuffers[0] >> (rules[ruleNum].input & 0x1F)) & 1;
+
+ if ((2 == ruleActivity) || (inputActivity == ruleActivity)) {
+ writeOutputBuffers[0] |= rules[ruleNum].setMask[0];
+ //writeOutputBuffers[1] |= rules[ruleNum].setMask[1];
+ //writeOutputBuffers[2] |= rules[ruleNum].setMask[2];
+
+ writeOutputBuffers[0] &= ~rules[ruleNum].clearMask[0];
+ //writeOutputBuffers[1] &= ~rules[ruleNum].clearMask[1];
+ //writeOutputBuffers[2] &= ~rules[ruleNum].clearMask[2];
+ }
+ }
+
+ }
+ }
+
+ /* index 6005-01 configured to enable interrupt messages */
+ if (bInputInterruptEnable) {
+
+ /* if change is within index 6006-01, interrupt mask */
+ if (inputChangeMask[0] & inputInterruptMask[0]) {
+
+ /* send a message immediately */
+ PostTPDO(0x181);
+ }
+
+ }
+
+ prevInputBuffers[0] = readInputBuffers[0];
+}
+
+/******************************************************************************
+ * SYNC Implementation
+ ******************************************************************************
+ */
+
+void Node_pin0808::OnSync (uint8_t counter)
+{
+
+}
+
+/******************************************************************************
+ * NMT Control Implementation
+ ******************************************************************************
+ */
+
+void Node_pin0808::OnInitialize (void)
+{
+ printf(" Node_pin0808::INITIALIZE!\r\n");
+
+ mbedOutputs = 0xFFFF;
+ wait(1.0);
+ mbedOutputs = 0;
+
+ prevOutputBuffers[0] = 0;
+ writeOutputBuffers[0] = 0;
+
+ prevInputBuffers[0] = 0;
+ readInputBuffers[0] = 0;
+}
+
+void Node_pin0808::OnPreoperational (void)
+{
+ printf(" Node_pin0808::PRE-OPERATIONAL!\r\n");
+}
+
+void Node_pin0808::OnOperational (void)
+{
+ printf(" Node_pin0808::OPERATIONAL!\r\n");
+
+ mbedOutputs = (writeOutputBuffers[0] << 16);
+}
+
+void Node_pin0808::OnStopped (void)
+{
+ printf(" Node_pin0808::STOPPED!\r\n");
+
+ mbedOutputs = 0;
+}
+
+/******************************************************************************
+ * Object Dictionary Handling
+ ******************************************************************************
+ */
+
+ObjectData * Node_pin0808::ScanIndex(IndexSize index)
+{
+ ObjectData * result = 0;
+
+ switch(index) {
+ case 0x1200: result = &dictionary[0]; break;
+ case 0x1400: result = &dictionary[1]; break;
+ case 0x1401: result = &dictionary[2]; break;
+ case 0x1402: result = &dictionary[3]; break;
+ case 0x1403: result = &dictionary[4]; break;
+ case 0x1600: result = &dictionary[5]; break;
+ case 0x1601: result = &dictionary[6]; break;
+ case 0x1602: result = &dictionary[7]; break;
+ case 0x1603: result = &dictionary[8]; break;
+ case 0x1800: result = &dictionary[10]; break;
+ case 0x1A00: result = &dictionary[11]; break;
+ case 0x2001: result = &dictionary[12]; break;
+ case 0x2002: result = &dictionary[13]; break;
+ case 0x2100: result = &dictionary[14]; break;
+ case 0x2200: result = &dictionary[15]; break;
+ case 0x6000: result = &dictionary[16]; break;
+ case 0x6005: result = &dictionary[17]; break;
+ case 0x6006: result = &dictionary[18]; break;
+ case 0x6200: result = &dictionary[19]; break;
+ default:
+ // TODO add error handling
+ break;
+ }
+
+ return result;
+}
+
+} /* namespace ppCANOpen */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Application/source/SerialBuffered.cpp Sat Mar 19 01:44:35 2016 +0000
@@ -0,0 +1,99 @@
+#include "mbed.h"
+#include "SerialBuffered.h"
+
+/**
+ * Create a buffered serial class.
+ *
+ * @param tx A pin for transmit.
+ * @param rx A pin for receive.
+ */
+SerialBuffered::SerialBuffered(PinName tx, PinName rx) : Serial(tx, rx) {
+ indexContentStart = 0;
+ indexContentEnd = 0;
+ timeout = 1;
+ attach(this, &SerialBuffered::handleInterrupt);
+}
+
+/**
+ * Destroy.
+ */
+SerialBuffered::~SerialBuffered() {
+}
+
+/**
+ * Set timeout for getc().
+ *
+ * @param ms milliseconds. (-1:Disable timeout)
+ */
+void SerialBuffered::setTimeout(int ms) {
+ timeout = ms;
+}
+
+/**
+ * Read requested bytes.
+ *
+ * @param bytes A pointer to a buffer.
+ * @param requested Length.
+ *
+ * @return Readed byte length.
+ */
+size_t SerialBuffered::readBytes(uint8_t *bytes, size_t requested) {
+ int i = 0;
+ while (i < requested) {
+ int c = getc();
+ if (c < 0) {
+ break;
+ }
+ bytes[i] = c;
+ i++;
+ }
+ return i;
+}
+
+/**
+ * Get a character.
+ *
+ * @return A character. (-1:timeout)
+ */
+int SerialBuffered::getc() {
+ timer.reset();
+ timer.start();
+ while (indexContentStart == indexContentEnd) {
+ wait_ms(1);
+ if ((timeout > 0) && (timer.read_ms() > timeout)) {
+ /*
+ * Timeout occured.
+ */
+ // printf("Timeout occured.\n");
+ return EOF;
+ }
+ }
+ timer.stop();
+
+ uint8_t result = buffer[indexContentStart++];
+ indexContentStart = indexContentStart % BUFFERSIZE;
+
+ return result;
+}
+
+/**
+ * Returns 1 if there is a character available to read, 0 otherwise.
+ */
+int SerialBuffered::readable() {
+ return indexContentStart != indexContentEnd;
+}
+
+void SerialBuffered::handleInterrupt() {
+ while (Serial::readable()) {
+ if (indexContentStart == ((indexContentEnd + 1) % BUFFERSIZE)) {
+ /*
+ * Buffer overrun occured.
+ */
+ // printf("Buffer overrun occured.\n");
+ Serial::getc();
+ } else {
+ buffer[indexContentEnd++] = Serial::getc();
+ indexContentEnd = indexContentEnd % BUFFERSIZE;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Application/source/main.cpp Sat Mar 19 01:44:35 2016 +0000
@@ -0,0 +1,71 @@
+
+/** @file
+ * @brief main program entry
+ */
+
+#include "mbed.h"
+#include "CAN.h"
+
+#include "ppCANOpen.h"
+#include "Node_pin0808.h"
+
+DigitalOut boardLed (LED1);
+
+void InputScan ()
+{
+ boardLed = !boardLed;
+}
+
+
+int main()
+{
+
+ printf ("\r\n----- MAIN -----\r\n");
+
+ /* blinker task*/
+ boardLed = 0;
+
+//#define MASTER
+#ifdef MASTER
+
+ /* CanOpen start */
+ ServiceProvider service;
+ printf ("----- READY -----\r\n");
+
+ Node_pin0808 node1(2, &service);
+ //Node_pin0808 node2(&service);
+
+ service.PostNmtControl(1, NMT_CS_RESET_NODE);
+ service.Run();
+ service.PostNmtControl(2, NMT_CS_START);
+ service.Run();
+ service.PostNmtControl(3, NMT_CS_START);
+ service.Run();
+ service.PostNmtControl(4, NMT_CS_START);
+ service.Run();
+ service.PostNmtControl(5, NMT_CS_START);
+ service.Run();
+ service.PostNmtControl(6, NMT_CS_START);
+ service.Run();
+
+ while (1) {
+ service.Run();
+ }
+
+#else
+
+ /* CanOpen start */
+ ServiceProvider service;
+ printf ("----- READY -----\r\n");
+
+ Node_pin0808 node1(3, &service);
+
+ while (1) {
+ service.Run();
+ }
+
+#endif
+
+ printf ("----- END -------\r\n\n");
+
+}
--- a/CANnucleo.lib Wed Dec 23 10:38:02 2015 +0000 +++ b/CANnucleo.lib Sat Mar 19 01:44:35 2016 +0000 @@ -1,1 +1,1 @@ -https://developer.mbed.org/users/hudakz/code/CANnucleo/#a3e2be3d49a2 +https://developer.mbed.org/users/ptpaterson/code/CANnucleo/#cdab1fd4ff26
--- a/main.cpp Wed Dec 23 10:38:02 2015 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,129 +0,0 @@
-/*
- * An example showing how to use the CANnucleo library:
- *
- * Two affordable (less than $4 on ebay) STM32F103C8T6 boards (20kB SRAM, 64kB Flash),
- * compatible with the NUCLEO-F103RB platform (20kB SRAM, 128kB Flash),
- * are connected to the same CAN bus via transceivers (MCP2551 or TJA1040, or etc.).
- * CAN transceivers are not part of NUCLEO boards, therefore must be added by you.
- * Remember also that CAN bus (even a short one) must be terminated with 120 Ohm resitors at both ends.
- *
- * For more details see the wiki page <https://developer.mbed.org/users/hudakz/code/CAN_Nucleo_Hello/>
- *
- * NOTE: If you'd like to use the official NUCLEO-F103RB boards
- * comment out the line #define TARGET_STM32F103C8T6 1
- *
- * The same code is used for both NUCLEO boards, but:
- * For board #1 compile the example without any change.
- * For board #2 comment out the line #define BOARD1 1 before compiling
- *
- * Once the binaries have been downloaded to the boards reset board #1.
- *
- */
-
-#include "mbed.h"
-#include "CAN.h"
-
-#define BOARD1 1 // comment out this line when compiling for board #2
-
-#if defined(BOARD1)
- #define RX_ID 0x100
- #define TX_ID 0x101
-#else
- #define RX_ID 0x101
- #define TX_ID 0x100
-#endif
-
-// See wiki page <https://developer.mbed.org/users/hudakz/code/CAN_Nucleo_Hello/>
-//#define TARGET_STM32F103C8T6 1 // comment out this line if you'd like to use the official NUCLEO-F103RB boards
-
-#if defined(TARGET_STM32F103C8T6)
- DigitalOut led(PC_13);
-#else
- DigitalOut led(LED1);
-#endif
-
-int ledReceived;
-Timer timer;
-CAN can(PA_11, PA_12); // CAN Rx pin name, CAN Tx pin name, Automatic recovery from bus-off state enabled by default
-CANMessage rxMsg;
-CANMessage txMsg;
-int counter = 0;
-volatile bool msgAvailable = false;
-
-/**
- * @brief 'CAN receive-complete' interrup handler.
- * @note Called on arrival of new CAN message.
- * Keep it as short as possible.
- * @param
- * @retval
- */
-void onMsgReceived() {
- msgAvailable = true;
-}
-
-/**
- * @brief Main
- * @note
- * @param
- * @retval
- */
-int main() {
- can.frequency(1000000); // set bit rate to 1Mbps
- can.attach(&onMsgReceived, CAN::RxIrq); // attach 'CAN receive-complete' interrupt handler
-
-#if defined(BOARD1)
- #if defined(TARGET_STM32F103C8T6)
- led = 0; // turn LED on
- #else
- led = 1; // turn LED on
- #endif
- timer.start();
-#else
- #if defined(TARGET_STM32F103C8T6)
- led = 1; // turn LED off
- #else
- led = 0; // turn LED off
- #endif
-#endif
-
- while(1) {
- if(timer.read() >= 1.0) { // check for timeout
- timer.stop(); // stop timer
- timer.reset(); // reset timer (to avaoid repeated send)
- counter++; // increment counter
- txMsg.clear(); // clear Tx message storage
- txMsg.id = TX_ID; // set ID
- txMsg << counter; // append first data item (make sure that CAN message total data lenght <= 8 bytes!)
- txMsg << led.read(); // append second data item (make sure that CAN message total data lenght <= 8 bytes!)
- can.write(txMsg); // transmit message
- printf("CAN message sent\r\n");
-
- #if defined(TARGET_STM32F103C8T6)
- led = 1; // turn LED off
- #else
- led = 0; // turn LED off
- #endif
- }
- if(msgAvailable) {
- msgAvailable = false; // reset flag for next use
- can.read(rxMsg); // read message into Rx message storage
- printf("CAN message received:\r\n");
- printf(" ID = %#x\r\n", rxMsg.id);
- printf(" Type = %d\r\n", rxMsg.type);
- printf(" Format = %d\r\n", rxMsg.format);
- printf(" Length = %d\r\n", rxMsg.len);
- printf(" Data =");
- for(int i = 0; i < rxMsg.len; i++)
- printf(" %x", rxMsg.data[i]);
- printf("\r\n");
- if(rxMsg.id == RX_ID) { // if ID matches
- rxMsg >> counter; // extract first data item
- rxMsg >> ledReceived; // extract second data item
- led = ledReceived; // set LED
- printf("counter = %d\r\n", counter);
- timer.start();
- }
- }
- }
-}
-
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ppCANOpen.lib Sat Mar 19 01:44:35 2016 +0000 @@ -0,0 +1,1 @@ +http://developer.mbed.org/users/ptpaterson/code/ppCANOpen/#22a337cdc0e3