I am no longer actively working on the ppCANOpen library, however, I want to publish this project so that anyone who wants to pick up any of the pieces can have a good example. This is a a project I was working on using the ppCANOpen library. It has a pretty in deep use of the object dictionary structure. And a number of functions to control high voltage pinball drivers, if you're into that sort of thing.
Dependencies: CANnucleo mbed ppCANOpen
Application/source/Node_pin0808.cpp
- Committer:
- ptpaterson
- Date:
- 2016-03-19
- Revision:
- 10:ec59d628ebdc
File content as of revision 10:ec59d628ebdc:
/** ****************************************************************************** * @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 */