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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Node_pin0808.cpp Source File

Node_pin0808.cpp

Go to the documentation of this file.
00001 /**
00002  ******************************************************************************
00003  * @file
00004  * @author  Paul Paterson
00005  * @version
00006  * @date    2015-12-14
00007  * @brief   CANOpen implementation library
00008  ******************************************************************************
00009  * @attention
00010  *
00011  * <h2><center>&copy; COPYRIGHT(c) 2015 Paul Paterson
00012  *
00013  * All rights reserved.
00014 
00015  This program is free software: you can redistribute it and/or modify
00016  it under the terms of the GNU General Public License as published by
00017  the Free Software Foundation, either version 3 of the License, or
00018  (at your option) any later version.
00019 
00020  This program is distributed in the hope that it will be useful,
00021  but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023  GNU General Public License for more details.
00024 
00025  You should have received a copy of the GNU General Public License
00026  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00027  */
00028 
00029 #include "Node_pin0808.h"
00030 #include "ServiceProvider.h"
00031 
00032 #include "stdio.h"
00033 #include "mbed.h"
00034 
00035 PortIn mbedInputs(PortB, 0x00FF);
00036 PortOut mbedOutputs(PortB, 0xFF00);
00037 
00038 namespace ppCANOpen
00039 {
00040 
00041 /******************************************************************************
00042  * Constructor/Destructor
00043  ******************************************************************************
00044  */
00045 
00046 Node_pin0808::Node_pin0808 (int id, ServiceProvider * provider, int bLoop)
00047     : Node(id, provider, bLoop)
00048 {
00049     dictionary = new ObjectData[22];
00050 
00051 
00052     /* Init values ***********************************************************/
00053     memset(prevInputBuffers, 0, sizeof(prevInputBuffers));
00054     memset(inputDebounce,    0, sizeof(inputDebounce));
00055     
00056     memset(prevOutputBuffers,0, sizeof(prevOutputBuffers));
00057 
00058     /* Init Object Dictionary ************************************************/
00059 
00060     /* Communication Objects ================================================*/
00061     
00062     /* SDO ------------------------------------------------------------------*/
00063     /* index 0x1200  */
00064     Obj1200_highestSubIndex = 2;
00065     Obj1200_ReceiveCobId    = 0x600 + nodeId;
00066     Obj1200_TransmitCobId   = 0x580 + nodeId;
00067     Obj1200_entries[0] = EntryData((void*)&Obj1200_highestSubIndex, sizeof(uint8_t),  EntryData::TYPE_UINT8,  EntryData::PROPERTY_READABLE);
00068     Obj1200_entries[1] = EntryData((void*)&Obj1200_ReceiveCobId,    sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00069     Obj1200_entries[2] = EntryData((void*)&Obj1200_TransmitCobId,   sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00070     Obj1200 = ObjectData(Obj1200_entries, 0x1200, sizeof(Obj1200_entries) / sizeof(Obj1200_entries[0]));
00071     
00072     /* RPDO -----------------------------------------------------------------*/
00073     /* index 0x1400  */
00074     Obj1400_highestSubIndex     = 5;
00075     Obj1400_CobId               = 0x200 + nodeId;
00076     Obj1400_TransmissionType    = 1;
00077     Obj1400_InhibitTime         = 0;
00078     Obj1400_CompatibilityEntry  = 0;
00079     Obj1400_EventTimer          = 0;
00080     Obj1400_entries[0] = EntryData((void*)&Obj1400_highestSubIndex,    sizeof(uint8_t),  EntryData::TYPE_UINT8,  EntryData::PROPERTY_READABLE);
00081     Obj1400_entries[1] = EntryData((void*)&Obj1400_CobId,              sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00082     Obj1400_entries[2] = EntryData((void*)&Obj1400_TransmissionType,   sizeof(uint8_t),  EntryData::TYPE_UINT8,  EntryData::PROPERTY_READABLE);
00083     Obj1400_entries[3] = EntryData((void*)&Obj1400_InhibitTime,        sizeof(uint16_t), EntryData::TYPE_UINT16, EntryData::PROPERTY_READABLE);
00084     Obj1400_entries[4] = EntryData((void*)&Obj1400_CompatibilityEntry, sizeof(uint8_t),  EntryData::TYPE_UINT8,  EntryData::PROPERTY_READABLE);
00085     Obj1400_entries[5] = EntryData((void*)&Obj1400_EventTimer,         sizeof(uint16_t), EntryData::TYPE_UINT16, EntryData::PROPERTY_READABLE);
00086     Obj1400 = ObjectData(Obj1400_entries, 0x1400, sizeof(Obj1400_entries) / sizeof(Obj1400_entries[0]));
00087 
00088     /* index 0x1401  */
00089     Obj1401_highestSubIndex     = 5;
00090     Obj1401_CobId               = 0x300 + nodeId;
00091     Obj1401_TransmissionType    = 1;
00092     Obj1401_InhibitTime         = 0;
00093     Obj1401_CompatibilityEntry  = 0;
00094     Obj1401_EventTimer          = 0;
00095     Obj1401_entries[0] = EntryData((void*)&Obj1401_highestSubIndex,    sizeof(uint8_t),  EntryData::TYPE_UINT8,  EntryData::PROPERTY_READABLE);
00096     Obj1401_entries[1] = EntryData((void*)&Obj1401_CobId,              sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00097     Obj1401_entries[2] = EntryData((void*)&Obj1401_TransmissionType,   sizeof(uint8_t),  EntryData::TYPE_UINT8,  EntryData::PROPERTY_READABLE);
00098     Obj1401_entries[3] = EntryData((void*)&Obj1401_InhibitTime,        sizeof(uint16_t), EntryData::TYPE_UINT16, EntryData::PROPERTY_READABLE);
00099     Obj1401_entries[4] = EntryData((void*)&Obj1401_CompatibilityEntry, sizeof(uint8_t),  EntryData::TYPE_UINT8,  EntryData::PROPERTY_READABLE);
00100     Obj1401_entries[5] = EntryData((void*)&Obj1401_EventTimer,         sizeof(uint16_t), EntryData::TYPE_UINT16, EntryData::PROPERTY_READABLE);
00101     Obj1401 = ObjectData(Obj1401_entries, 0x1401, sizeof(Obj1401_entries) / sizeof(Obj1401_entries[0]));
00102 
00103     /* index 0x1402  */
00104     Obj1402_highestSubIndex     = 5;
00105     Obj1402_CobId               = 0x400 + nodeId;
00106     Obj1402_TransmissionType    = 1;
00107     Obj1402_InhibitTime         = 0;
00108     Obj1402_CompatibilityEntry  = 0;
00109     Obj1402_EventTimer          = 0;
00110     Obj1402_entries[0] = EntryData((void*)&Obj1402_highestSubIndex,    sizeof(uint8_t),  EntryData::TYPE_UINT8,  EntryData::PROPERTY_READABLE);
00111     Obj1402_entries[1] = EntryData((void*)&Obj1402_CobId,              sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00112     Obj1402_entries[2] = EntryData((void*)&Obj1402_TransmissionType,   sizeof(uint8_t),  EntryData::TYPE_UINT8,  EntryData::PROPERTY_READABLE);
00113     Obj1402_entries[3] = EntryData((void*)&Obj1402_InhibitTime,        sizeof(uint16_t), EntryData::TYPE_UINT16, EntryData::PROPERTY_READABLE);
00114     Obj1402_entries[4] = EntryData((void*)&Obj1402_CompatibilityEntry, sizeof(uint8_t),  EntryData::TYPE_UINT8,  EntryData::PROPERTY_READABLE);
00115     Obj1402_entries[5] = EntryData((void*)&Obj1402_EventTimer,         sizeof(uint16_t), EntryData::TYPE_UINT16, EntryData::PROPERTY_READABLE);
00116     Obj1402 = ObjectData(Obj1402_entries, 0x1402, sizeof(Obj1402_entries) / sizeof(Obj1402_entries[0]));
00117 
00118     /* index 0x1403  */
00119     Obj1403_highestSubIndex     = 5;
00120     Obj1403_CobId               = 0x181;
00121     Obj1403_TransmissionType    = 1;
00122     Obj1403_InhibitTime         = 0;
00123     Obj1403_CompatibilityEntry  = 0;
00124     Obj1403_EventTimer          = 0;
00125     Obj1403_entries[0] = EntryData((void*)&Obj1403_highestSubIndex,    sizeof(uint8_t),  EntryData::TYPE_UINT8,  EntryData::PROPERTY_READABLE);
00126     Obj1403_entries[1] = EntryData((void*)&Obj1403_CobId,              sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00127     Obj1403_entries[2] = EntryData((void*)&Obj1403_TransmissionType,   sizeof(uint8_t),  EntryData::TYPE_UINT8,  EntryData::PROPERTY_READABLE);
00128     Obj1403_entries[3] = EntryData((void*)&Obj1403_InhibitTime,        sizeof(uint16_t), EntryData::TYPE_UINT16, EntryData::PROPERTY_READABLE);
00129     Obj1403_entries[4] = EntryData((void*)&Obj1403_CompatibilityEntry, sizeof(uint8_t),  EntryData::TYPE_UINT8,  EntryData::PROPERTY_READABLE);
00130     Obj1403_entries[5] = EntryData((void*)&Obj1403_EventTimer,         sizeof(uint16_t), EntryData::TYPE_UINT16, EntryData::PROPERTY_READABLE);
00131     Obj1403 = ObjectData(Obj1403_entries, 0x1403, sizeof(Obj1403_entries) / sizeof(Obj1403_entries[0]));
00132 
00133     /* index 0x1600  */
00134     Obj1600_highestSubIndex = 1;
00135     Obj1600_Map             = 0x62000108;
00136     Obj1600_entries[0] = EntryData((void*)&Obj1600_highestSubIndex, sizeof(uint8_t),  EntryData::TYPE_UINT8,  EntryData::PROPERTY_READABLE);
00137     Obj1600_entries[1] = EntryData((void*)&Obj1600_Map,             sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00138     Obj1600 = ObjectData(Obj1600_entries, 0x1600, sizeof(Obj1600_entries) / sizeof(Obj1600_entries[0]));
00139     
00140     /* index 0x1601  */
00141     Obj1601_highestSubIndex = 1;
00142     Obj1601_Map             = 0x20010140;
00143     Obj1601_entries[0] = EntryData((void*)&Obj1601_highestSubIndex, sizeof(uint8_t),  EntryData::TYPE_UINT8,  EntryData::PROPERTY_READABLE);
00144     Obj1601_entries[1] = EntryData((void*)&Obj1601_Map,             sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00145     Obj1601 = ObjectData(Obj1601_entries, 0x1601, sizeof(Obj1601_entries) / sizeof(Obj1601_entries[0]));
00146 
00147     /* index 0x1602  */
00148     Obj1602_highestSubIndex = 1;
00149     Obj1602_Map             = 0x22000140;
00150     Obj1602_entries[0] = EntryData((void*)&Obj1602_highestSubIndex, sizeof(uint8_t),  EntryData::TYPE_UINT8,  EntryData::PROPERTY_READABLE);
00151     Obj1602_entries[1] = EntryData((void*)&Obj1602_Map,             sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00152     Obj1602 = ObjectData(Obj1602_entries, 0x1602, sizeof(Obj1602_entries) / sizeof(Obj1602_entries[0]));
00153 
00154     /* index 0x1603  */
00155     Obj1603_highestSubIndex = 1;
00156     Obj1603_Map             = 0x22000238;
00157     Obj1603_entries[0] = EntryData((void*)&Obj1603_highestSubIndex, sizeof(uint8_t),  EntryData::TYPE_UINT8,  EntryData::PROPERTY_READABLE);
00158     Obj1603_entries[1] = EntryData((void*)&Obj1603_Map,             sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00159     Obj1603 = ObjectData(Obj1603_entries, 0x1603, sizeof(Obj1603_entries) / sizeof(Obj1603_entries[0]));
00160 
00161     /* TPDO -----------------------------------------------------------------*/
00162     /* index 0x1800  */
00163     Obj1800_highestSubIndex     = 5;
00164     Obj1800_CobId               = 0x181;
00165     Obj1800_TransmissionType    = 0xFE;  /* event driven Manuf specific */
00166     Obj1800_InhibitTime         = 0;     // TODO review if this is needed
00167     Obj1800_CompatibilityEntry  = 0;
00168     Obj1800_EventTimer          = 0;
00169     Obj1800_entries[0] = EntryData((void*)&Obj1800_highestSubIndex,    sizeof(uint8_t),  EntryData::TYPE_UINT8,  EntryData::PROPERTY_READABLE);
00170     Obj1800_entries[1] = EntryData((void*)&Obj1800_CobId,              sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00171     Obj1800_entries[2] = EntryData((void*)&Obj1800_TransmissionType,   sizeof(uint8_t),  EntryData::TYPE_UINT8,  EntryData::PROPERTY_READABLE);
00172     Obj1800_entries[3] = EntryData((void*)&Obj1800_InhibitTime,        sizeof(uint16_t), EntryData::TYPE_UINT16, EntryData::PROPERTY_READABLE);
00173     Obj1800_entries[4] = EntryData((void*)&Obj1800_CompatibilityEntry, sizeof(uint8_t),  EntryData::TYPE_UINT8,  EntryData::PROPERTY_READABLE);
00174     Obj1800_entries[5] = EntryData((void*)&Obj1800_EventTimer,         sizeof(uint16_t), EntryData::TYPE_UINT16, EntryData::PROPERTY_READABLE);
00175     Obj1800 = ObjectData(Obj1800_entries, 0x1800, sizeof(Obj1800_entries) / sizeof(Obj1800_entries[0]));
00176 
00177     /* index 0x1A00  */
00178     Obj1A00_highestSubIndex = 5;
00179     Obj1A00_MapInput        = 0x60000108;
00180     Obj1A00_MapVoid16       = 0x00000010;
00181     Obj1A00_MapChange       = 0x21000108;
00182     Obj1A00_MapSourceId     = 0x21000208;
00183     Obj1A00_entries[0] = EntryData((void*)&Obj1A00_highestSubIndex, sizeof(uint8_t),  EntryData::TYPE_UINT8,  EntryData::PROPERTY_READABLE);
00184     Obj1A00_entries[1] = EntryData((void*)&Obj1A00_MapInput,        sizeof(uint8_t),  EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00185     Obj1A00_entries[2] = EntryData((void*)&Obj1A00_MapVoid16,       sizeof(uint16_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00186     Obj1A00_entries[3] = EntryData((void*)&Obj1A00_MapChange,       sizeof(uint8_t),  EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00187     Obj1A00_entries[4] = EntryData((void*)&Obj1A00_MapVoid16,       sizeof(uint16_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00188     Obj1A00_entries[5] = EntryData((void*)&Obj1A00_MapSourceId,     sizeof(uint8_t),  EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00189     Obj1A00 = ObjectData(Obj1A00_entries, 0x1A00, sizeof(Obj1A00_entries) / sizeof(Obj1A00_entries[0]));
00190 
00191 
00192     /* Manufacturer Specific Objects ========================================*/
00193 
00194     /* index 0x2001 : Pin Output Configurations */
00195     Obj2001_highestSubIndex = 8;
00196     memset(&writeOutputConfig, 0, sizeof(writeOutputConfig));
00197     memset(outputConfigs, 0, sizeof(outputConfigs));
00198     outputConfigs[0].type       = 0x08;
00199     memset(outputTimers, 0, sizeof(outputTimers));
00200     Obj2001_entries[0] = EntryData((void*)&Obj2001_highestSubIndex, sizeof(uint8_t),  EntryData::TYPE_UINT8,  EntryData::PROPERTY_READABLE);
00201     Obj2001_entries[1] = EntryData((void*)&writeOutputConfig, sizeof(OutputConfiguration), EntryData::TYPE_UINT64, EntryData::PROPERTY_READ_WRITEABLE);
00202     Obj2001_entries[2] = EntryData((void*)&outputConfigs[0],  sizeof(OutputConfiguration), EntryData::TYPE_UINT64, EntryData::PROPERTY_READ_WRITEABLE);
00203     Obj2001_entries[3] = EntryData((void*)&outputConfigs[1],  sizeof(OutputConfiguration), EntryData::TYPE_UINT64, EntryData::PROPERTY_READ_WRITEABLE);
00204     Obj2001_entries[4] = EntryData((void*)&outputConfigs[2],  sizeof(OutputConfiguration), EntryData::TYPE_UINT64, EntryData::PROPERTY_READ_WRITEABLE);
00205     Obj2001_entries[5] = EntryData((void*)&outputConfigs[3],  sizeof(OutputConfiguration), EntryData::TYPE_UINT64, EntryData::PROPERTY_READ_WRITEABLE);
00206     Obj2001_entries[6] = EntryData((void*)&outputConfigs[4],  sizeof(OutputConfiguration), EntryData::TYPE_UINT64, EntryData::PROPERTY_READ_WRITEABLE);
00207     Obj2001_entries[7] = EntryData((void*)&outputConfigs[5],  sizeof(OutputConfiguration), EntryData::TYPE_UINT64, EntryData::PROPERTY_READ_WRITEABLE);
00208     Obj2001_entries[8] = EntryData((void*)&outputConfigs[6],  sizeof(OutputConfiguration), EntryData::TYPE_UINT64, EntryData::PROPERTY_READ_WRITEABLE);
00209     Obj2001_entries[9] = EntryData((void*)&outputConfigs[7],  sizeof(OutputConfiguration), EntryData::TYPE_UINT64, EntryData::PROPERTY_READ_WRITEABLE);
00210     Obj2001 = ObjectData(Obj2001_entries, 0x2001, sizeof(Obj2001_entries) / sizeof(Obj2001_entries[0]));
00211 
00212     /* index 0x2002 : Output Schedule Configuration */
00213     Obj2002_highestSubIndex = 1;
00214     scheduleConfig  = 0x01;
00215     schedules[0] = 0xFF00F0F0;
00216     Obj2002_entries[0] = EntryData((void*)&Obj2002_highestSubIndex, sizeof(uint8_t),  EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
00217     Obj2002_entries[1] = EntryData((void*)&scheduleConfig, sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READ_WRITEABLE);
00218     Obj2002_entries[2] = EntryData((void*)&schedules[0],   sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READ_WRITEABLE);
00219     Obj2002_entries[3] = EntryData((void*)&schedules[1],   sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READ_WRITEABLE);
00220     Obj2002_entries[4] = EntryData((void*)&schedules[2],   sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READ_WRITEABLE);
00221     Obj2002_entries[5] = EntryData((void*)&schedules[3],   sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READ_WRITEABLE);
00222     Obj2002_entries[6] = EntryData((void*)&schedules[4],   sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READ_WRITEABLE);
00223     Obj2002_entries[7] = EntryData((void*)&schedules[5],   sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READ_WRITEABLE);
00224     Obj2002_entries[8] = EntryData((void*)&schedules[6],   sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READ_WRITEABLE);
00225     Obj2002_entries[9] = EntryData((void*)&schedules[7],   sizeof(uint32_t), EntryData::TYPE_UINT32, EntryData::PROPERTY_READ_WRITEABLE);
00226     Obj2002 = ObjectData(Obj2002_entries, 0x2002, sizeof(Obj2002_entries) / sizeof(Obj2002_entries[0]));
00227 
00228     /* Index 2100 */
00229     Obj2100_highestSubIndex = 2;
00230     inputChangeMask[0] = 0;
00231     /* nodeId; */
00232     Obj2100_entries[0] = EntryData((void*)&Obj2100_highestSubIndex, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
00233     Obj2100_entries[1] = EntryData((void*)&inputChangeMask[0],      sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
00234     Obj2100_entries[2] = EntryData((void*)&nodeId,                  sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
00235     Obj2100 = ObjectData(Obj2100_entries, 0x2100, sizeof(Obj2100_entries) / sizeof(Obj2100_entries[0]));
00236     
00237     /* Index 2200 */
00238     Obj2200_highestSubIndex = 2;
00239     memset(&writeRule,          0, sizeof(AutotriggerRule));
00240     memset(&autotriggerMessage, 0, sizeof(AutotriggerMessage));
00241     memset(rules, 0, sizeof(rules));
00242     Obj2200_entries[0]  = EntryData((void*)&Obj2200_highestSubIndex, sizeof(uint8_t),            EntryData::TYPE_UINT8,  EntryData::PROPERTY_READABLE);
00243     Obj2200_entries[1]  = EntryData((void*)&writeRule,               sizeof(AutotriggerRule),    EntryData::TYPE_UINT32, EntryData::PROPERTY_READ_WRITEABLE);
00244     Obj2200_entries[2]  = EntryData((void*)&autotriggerMessage,      sizeof(AutotriggerMessage), EntryData::TYPE_UINT32, EntryData::PROPERTY_READ_WRITEABLE);
00245     Obj2200_entries[3]  = EntryData((void*)&rules[0],                sizeof(AutotriggerRule),    EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00246     Obj2200_entries[4]  = EntryData((void*)&rules[1],                sizeof(AutotriggerRule),    EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00247     Obj2200_entries[5]  = EntryData((void*)&rules[2],                sizeof(AutotriggerRule),    EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00248     Obj2200_entries[6]  = EntryData((void*)&rules[3],                sizeof(AutotriggerRule),    EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00249     Obj2200_entries[7]  = EntryData((void*)&rules[4],                sizeof(AutotriggerRule),    EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00250     Obj2200_entries[8]  = EntryData((void*)&rules[5],                sizeof(AutotriggerRule),    EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00251     Obj2200_entries[9]  = EntryData((void*)&rules[6],                sizeof(AutotriggerRule),    EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00252     Obj2200_entries[10] = EntryData((void*)&rules[7],                sizeof(AutotriggerRule),    EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00253     Obj2200_entries[11] = EntryData((void*)&rules[8],                sizeof(AutotriggerRule),    EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00254     Obj2200_entries[12] = EntryData((void*)&rules[9],                sizeof(AutotriggerRule),    EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00255     Obj2200_entries[13] = EntryData((void*)&rules[10],               sizeof(AutotriggerRule),    EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00256     Obj2200_entries[14] = EntryData((void*)&rules[11],               sizeof(AutotriggerRule),    EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00257     Obj2200_entries[15] = EntryData((void*)&rules[12],               sizeof(AutotriggerRule),    EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00258     Obj2200_entries[16] = EntryData((void*)&rules[13],               sizeof(AutotriggerRule),    EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00259     Obj2200_entries[17] = EntryData((void*)&rules[14],               sizeof(AutotriggerRule),    EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00260     Obj2200_entries[18] = EntryData((void*)&rules[15],               sizeof(AutotriggerRule),    EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00261     Obj2200_entries[19] = EntryData((void*)&rules[16],               sizeof(AutotriggerRule),    EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00262     Obj2200_entries[20] = EntryData((void*)&rules[17],               sizeof(AutotriggerRule),    EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00263     Obj2200_entries[21] = EntryData((void*)&rules[18],               sizeof(AutotriggerRule),    EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00264     Obj2200_entries[22] = EntryData((void*)&rules[19],               sizeof(AutotriggerRule),    EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00265     Obj2200_entries[23] = EntryData((void*)&rules[20],               sizeof(AutotriggerRule),    EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00266     Obj2200_entries[24] = EntryData((void*)&rules[21],               sizeof(AutotriggerRule),    EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00267     Obj2200_entries[25] = EntryData((void*)&rules[22],               sizeof(AutotriggerRule),    EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00268     Obj2200_entries[26] = EntryData((void*)&rules[23],               sizeof(AutotriggerRule),    EntryData::TYPE_UINT32, EntryData::PROPERTY_READABLE);
00269     Obj2200 = ObjectData(Obj2200_entries, 0x2200, sizeof(Obj2200_entries) / sizeof(Obj2200_entries[0]));
00270 
00271     /* Device Profile Specific Objects ======================================*/
00272 
00273     /* Index 6000 */
00274     Obj6000_highestSubIndex = 1;
00275     readInputBuffers[0]  = 0;
00276     Obj6000_entries[0] = EntryData((void*)&Obj6000_highestSubIndex, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
00277     Obj6000_entries[1] = EntryData((void*)&readInputBuffers,        sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
00278     Obj6000 = ObjectData(Obj6000_entries, 0x6000, sizeof(Obj6000_entries) / sizeof(Obj6000_entries[0]));
00279     
00280     /* Index 6005 */
00281     Obj6005_highestSubIndex = 1;
00282     bInputInterruptEnable   = 0x01;
00283     Obj6005_entries[0] = EntryData((void*)&Obj6005_highestSubIndex, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
00284     Obj6005_entries[1] = EntryData((void*)&bInputInterruptEnable,   sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READ_WRITEABLE);
00285     Obj6005 = ObjectData(Obj6005_entries, 0x6005, sizeof(Obj6005_entries) / sizeof(Obj6005_entries[0]));
00286     
00287     /* Index 6006 */
00288     Obj6006_highestSubIndex = 1;
00289     inputInterruptMask[0]      = 0xFF;
00290     Obj6006_entries[0] = EntryData((void*)&Obj6006_highestSubIndex, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
00291     Obj6006_entries[1] = EntryData((void*)&inputInterruptMask,      sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READ_WRITEABLE);
00292     Obj6006 = ObjectData(Obj6006_entries, 0x6006, sizeof(Obj6006_entries) / sizeof(Obj6006_entries[0]));
00293 
00294     /* Index 6200 */
00295     Obj6200_highestSubIndex = 1;
00296     writeOutputBuffers[0] = 0;
00297     Obj6200_entries[0] = EntryData((void*)&Obj6200_highestSubIndex, sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READABLE);
00298     Obj6200_entries[1] = EntryData((void*)&writeOutputBuffers,      sizeof(uint8_t), EntryData::TYPE_UINT8, EntryData::PROPERTY_READ_WRITEABLE);
00299     Obj6200 = ObjectData(Obj6200_entries, 0x6200, sizeof(Obj6200_entries) / sizeof(Obj6200_entries[0]));
00300 
00301     /* Set up the whole dictionary */
00302     dictionary[0]  = Obj1200;
00303     dictionary[1]  = Obj1400;
00304     dictionary[2]  = Obj1401;
00305     dictionary[3]  = Obj1402;
00306     dictionary[4]  = Obj1403;
00307     dictionary[5]  = Obj1600;
00308     dictionary[6]  = Obj1601;
00309     dictionary[7]  = Obj1602;
00310     dictionary[8]  = Obj1603;
00311     dictionary[10] = Obj1800;
00312     dictionary[11] = Obj1A00;
00313     dictionary[12] = Obj2001;
00314     dictionary[13] = Obj2002;
00315     dictionary[14] = Obj2100;
00316     dictionary[15] = Obj2200;
00317     dictionary[16] = Obj6000;
00318     dictionary[17] = Obj6005;
00319     dictionary[18] = Obj6006;
00320     dictionary[19] = Obj6200;
00321 
00322 }
00323 
00324 Node_pin0808::~Node_pin0808(void)
00325 {
00326     delete dictionary;
00327 }
00328 
00329 /******************************************************************************
00330  * Application Run Implementation
00331  ******************************************************************************
00332  */
00333 
00334 void Node_pin0808::OnFixedUpdate (void)
00335 {
00336     /**************************************************************************
00337      * INPUTS
00338      **************************************************************************
00339      */
00340 
00341     uint8_t inputSample = ~(uint8_t)(mbedInputs.read());
00342     
00343     uint8_t inputChange = readInputBuffers[0] ^ inputSample; 
00344     
00345     /* Loop through all of the inputs */
00346     for (int in = 0; in < 8; in++) {
00347         if (inputChange & (1 << in)) {
00348             
00349             inputDebounce[in] += (uint8_t)(timeSinceLastTick);
00350             if (inputDebounce[in] > DEBOUNCE_TIME) {
00351                 readInputBuffers[0] &= ~(1 << in);
00352                 readInputBuffers[0] |=  (inputSample & (1 << in));
00353                 
00354                 inputDebounce[in] = 0; 
00355             }
00356             
00357         } else {
00358             inputDebounce[in] = 0;   
00359         }
00360     }
00361     
00362 
00363     /**************************************************************************
00364      * OUTPUTS
00365      **************************************************************************
00366      */
00367 
00368     /* create a copy of the current outputs and edit as we go */
00369     uint8_t newOutput = (uint8_t)(mbedOutputs >> 8);
00370 
00371     /* big operation, so let's only do it once! */
00372     int scheduleIndexer = 1 << ((timeCurrentTick * 100) / 3125) % 32;    
00373 
00374     /* Loop through all of the outputs */
00375     for (int out = 0; out < 8; out++) {
00376 
00377         if (scheduleConfig & (1 << out)) {
00378             
00379             if (schedules[out] & scheduleIndexer) {
00380                 writeOutputBuffers[0] |= (1 << out);
00381             } else {
00382                 writeOutputBuffers[0] &= ~(1 << out);
00383             }
00384         }
00385         
00386         /* update GPIO's immediately only if new signal was given */
00387         int outputBufferChanges = writeOutputBuffers[0] ^ prevOutputBuffers[0];
00388         
00389         if (outputBufferChanges & (1 << out)) {
00390             if ((1 << out) & writeOutputBuffers[0]) {
00391                 /* switched on */
00392                 newOutput |= (1 << out);
00393 
00394                 /* reset timers */
00395                 if (outputConfigs[out].type) {
00396                     outputTimers[out] = OutputConfiguration(outputConfigs[out]);
00397                 }
00398             } else {
00399                 /* switched off */
00400                 newOutput &= ~(1 << out);
00401                 memset(&outputTimers[out], 0, sizeof(outputTimers[out]));
00402             }
00403         }
00404 
00405         /* if there is a pulse run down the timer */
00406         if (outputTimers[out].type & 0x01) {
00407 
00408             if (outputTimers[out].pulse_ms >= timeSinceLastTick) {
00409                 outputTimers[out].pulse_ms -= timeSinceLastTick;
00410             } else {
00411                 /* time past would put timer below 0 */
00412                 outputTimers[out].pulse_ms = 0;
00413             }
00414 
00415             /* if time has run out */
00416             if (0 == outputTimers[out].pulse_ms) {
00417 
00418                 /* just turn off pulse */
00419                 outputTimers[out].type &= 0xFE;
00420                 newOutput &= ~(1 << out);
00421 
00422                 /* if there is a patter, then output buffer will stay on */
00423                 /* but if there is a pulsed-patter, then it should still turn off */
00424                 if (!(outputTimers[out].type & 0x02) ||
00425                         (outputTimers[out].type & (0x02 | 0x04))) {
00426                     /* turn buffer off */
00427                     outputTimers[out].type = 0;
00428                     writeOutputBuffers[0] &= ~(1 << out);
00429                 }
00430             }
00431         }
00432 
00433         /* two ways to patter:
00434          * wait until after pulse (pulse-then-patter),
00435          * or config so pulse happens at same time (pulsed-patter)
00436          */
00437         if (((outputTimers[out].type & 0x02)          && !(outputTimers[out].type & 0x01)) ||
00438                 ((outputTimers[out].type & (0x02 | 0x04)) &&  (outputTimers[out].type & 0x01))) {
00439 
00440             /* if output is on, run down pwm_on, else tun down pwm_off */
00441             uint8_t *pw_timer;
00442             if (newOutput & (1 << out)) {
00443                 pw_timer = &outputTimers[out].pwm_on;
00444             } else {
00445                 pw_timer = &outputTimers[out].pwm_off;
00446             }
00447 
00448             if (*pw_timer >= timeSinceLastTick) {
00449                 *pw_timer -= timeSinceLastTick;
00450             } else {
00451                 *pw_timer = 0;
00452             }
00453 
00454             if (*pw_timer == 0) {
00455                 newOutput ^= (1 << out);
00456 
00457                 outputTimers[out].pwm_on  = outputConfigs[out].pwm_on;
00458                 outputTimers[out].pwm_off = outputConfigs[out].pwm_off;
00459             }
00460         }
00461 
00462 
00463     }
00464 
00465     mbedOutputs = ((uint16_t)newOutput) << 8;
00466 
00467     prevOutputBuffers[0] = writeOutputBuffers[0];
00468 }
00469 
00470 void Node_pin0808::OnUpdate (void)
00471 {    
00472     /* Check for output configurations --------------------------------------*/
00473     if (writeOutputConfig.writeData) {
00474         uint8_t out = (uint8_t)(writeOutputConfig.writeData);
00475         
00476         writeOutputConfig.writeData = 0;
00477         outputConfigs[out] = writeOutputConfig;
00478         
00479         memset(&writeOutputConfig, 0, sizeof(writeOutputConfig));
00480     }
00481 
00482 
00483     /* Check for rule configurations ----------------------------------------*/
00484     if (writeRule.sourceId) {
00485         printf("      Configuring Rules...\r\n");
00486         if (writeRule.sourceId & 0x80) {
00487             /* write new rule*/
00488             
00489             /* scan through array of rules for available (8th bit cleared) */
00490             int ruleNum = 0;
00491             while (ruleNum < 24) {
00492                 if (!(rules[ruleNum].sourceId & 0x80)) {
00493                                         
00494                     rules[ruleNum] = writeRule;
00495                     printf("      Rule added: #%d\r\n", ruleNum);
00496                     ruleNum = 24;
00497                 } else {
00498                     ruleNum++;
00499                     if (ruleNum == 24) {
00500                         printf("      ERROR: Not enough rules available");
00501                     }
00502                 }
00503             }
00504             
00505         } else {
00506             /* clear rules */
00507             
00508             /* scan through array of rules matching input and disable */
00509             for (int ruleNum = 0; ruleNum < 24; ruleNum++) {
00510                 
00511                 /* check if rule enabled and input num matches */
00512                 if ((rules[ruleNum].sourceId & 0x80) &&
00513                    ((rules[ruleNum].sourceId & 0x7F) == writeRule.sourceId) &&
00514                    ((rules[ruleNum].input    & 0x1F) == (writeRule.input & 0x1F))) 
00515                 {
00516                     memset(&rules[ruleNum], 0, sizeof(AutotriggerRule));
00517                     printf("      Rule removed: #%d\r\n", ruleNum);
00518                 }
00519                 
00520             }
00521         }
00522     
00523         memset(&writeRule, 0, sizeof(AutotriggerRule));   
00524     }
00525 
00526     /* check for input changes  from other devices---------------------------*/
00527     if (autotriggerMessage.sourceId) {
00528         
00529         printf("      detected change from node: %#04x\r\n", (autotriggerMessage.sourceId & 0x7F));
00530         /* scan through array of rules matching inputs and direction */
00531         for (int ruleNum = 0; ruleNum < 24; ruleNum++) {
00532             
00533             /* check if rule enabled and input num matches */
00534             if ((rules[ruleNum].sourceId & 0x80) &&                                     /* rule is active AND */                  
00535                 (rules[ruleNum].sourceId == autotriggerMessage.sourceId) &&             /* rule source matches message source AND */ 
00536                 (autotriggerMessage.change[0] & (1 << (rules[ruleNum].input & 0x1F))))  /* change exists at input num */
00537             {
00538                 
00539                 int ruleActivity = rules[ruleNum].input >> 5;
00540                 int inputActivity = (autotriggerMessage.input[0] >> (rules[ruleNum].input & 0x1F)) & 1;
00541                 
00542                 printf("         id match:      %#04x\r\n", ruleNum);
00543                 printf("         ruleActivity:  %#04x\r\n", ruleActivity);
00544                 printf("         inputActivity: %#04x\r\n", inputActivity);
00545                 
00546                 if ((2 == ruleActivity) || (inputActivity == ruleActivity)) {
00547                     
00548                     printf("            activating Rule...\r\n");
00549                     printf("            setMask:   %#10x\r\n", rules[ruleNum].setMask[0]);
00550                     printf("            clearMask: %#10x\r\n", ~rules[ruleNum].clearMask[0]);
00551                     
00552                     writeOutputBuffers[0] |= rules[ruleNum].setMask[0];
00553                     //writeOutputBuffers[1] |= rules[ruleNum].setMask[1];
00554                     //writeOutputBuffers[2] |= rules[ruleNum].setMask[2];
00555                     
00556                     writeOutputBuffers[0] &= ~rules[ruleNum].clearMask[0];
00557                     //writeOutputBuffers[1] &= ~rules[ruleNum].clearMask[1];
00558                     //writeOutputBuffers[2] &= ~rules[ruleNum].clearMask[2];
00559                 }
00560             }
00561             
00562         }
00563         
00564         memset(&autotriggerMessage, 0, sizeof(AutotriggerMessage)); 
00565     }
00566 
00567     /* check for input changes from this device -----------------------------*/
00568     /* update Index 2101-01 */
00569     inputChangeMask[0] = readInputBuffers[0] ^ prevInputBuffers[0];
00570 
00571     /* check for rules against this devices inputs */
00572     if (inputChangeMask[0]) {
00573         /* scan through array of rules matching inputs and direction */
00574         for (int ruleNum = 0; ruleNum < 24; ruleNum++) {
00575             
00576             /* check if rule enabled and input num matches */
00577             if ((rules[ruleNum].sourceId & 0x80) &&                             /* rule is active AND */                  
00578                 ((rules[ruleNum].sourceId & 0x7F) == nodeId) &&                 /* rule source is this nodeId AND */ 
00579                 (inputChangeMask[0] & (1 << (rules[ruleNum].input & 0x1F))))    /* change exists at input num */
00580             {
00581                 
00582                 int ruleActivity = rules[ruleNum].input >> 5;
00583                 int inputActivity = (readInputBuffers[0] >> (rules[ruleNum].input & 0x1F)) & 1;
00584                 
00585                 if ((2 == ruleActivity) || (inputActivity == ruleActivity)) {
00586                     writeOutputBuffers[0] |= rules[ruleNum].setMask[0];
00587                     //writeOutputBuffers[1] |= rules[ruleNum].setMask[1];
00588                     //writeOutputBuffers[2] |= rules[ruleNum].setMask[2];
00589                     
00590                     writeOutputBuffers[0] &= ~rules[ruleNum].clearMask[0];
00591                     //writeOutputBuffers[1] &= ~rules[ruleNum].clearMask[1];
00592                     //writeOutputBuffers[2] &= ~rules[ruleNum].clearMask[2];
00593                 }
00594             }
00595             
00596         }
00597     }
00598 
00599     /* index 6005-01 configured to enable interrupt messages */
00600     if (bInputInterruptEnable) {
00601         
00602         /* if change is within index 6006-01, interrupt mask */
00603         if (inputChangeMask[0] & inputInterruptMask[0]) {
00604             
00605             /* send a message immediately */
00606             PostTPDO(0x181);
00607         }
00608         
00609     }
00610     
00611     prevInputBuffers[0] = readInputBuffers[0];
00612 }
00613 
00614 /******************************************************************************
00615  * SYNC Implementation
00616  ******************************************************************************
00617  */
00618 
00619 void Node_pin0808::OnSync (uint8_t counter)
00620 {
00621 
00622 }
00623 
00624 /******************************************************************************
00625  * NMT Control Implementation
00626  ******************************************************************************
00627  */
00628 
00629 void Node_pin0808::OnInitialize (void)
00630 {
00631     printf("      Node_pin0808::INITIALIZE!\r\n");
00632 
00633     mbedOutputs = 0xFFFF;
00634     wait(1.0);
00635     mbedOutputs = 0;
00636 
00637     prevOutputBuffers[0] = 0;
00638     writeOutputBuffers[0] = 0;
00639     
00640     prevInputBuffers[0] = 0;
00641     readInputBuffers[0] = 0;
00642 }
00643 
00644 void Node_pin0808::OnPreoperational (void)
00645 {
00646     printf("      Node_pin0808::PRE-OPERATIONAL!\r\n");
00647 }
00648 
00649 void Node_pin0808::OnOperational (void)
00650 {
00651     printf("      Node_pin0808::OPERATIONAL!\r\n");
00652 
00653     mbedOutputs = (writeOutputBuffers[0] << 16);
00654 }
00655 
00656 void Node_pin0808::OnStopped (void)
00657 {
00658     printf("      Node_pin0808::STOPPED!\r\n");
00659 
00660     mbedOutputs = 0;
00661 }
00662 
00663 /******************************************************************************
00664  * Object Dictionary Handling
00665  ******************************************************************************
00666  */
00667 
00668 ObjectData * Node_pin0808::ScanIndex(IndexSize index)
00669 {
00670     ObjectData * result = 0;
00671 
00672     switch(index) {
00673         case 0x1200: result = &dictionary[0]; break;
00674         case 0x1400: result = &dictionary[1]; break;
00675         case 0x1401: result = &dictionary[2]; break;
00676         case 0x1402: result = &dictionary[3]; break;
00677         case 0x1403: result = &dictionary[4]; break;
00678         case 0x1600: result = &dictionary[5]; break;
00679         case 0x1601: result = &dictionary[6]; break;
00680         case 0x1602: result = &dictionary[7]; break;
00681         case 0x1603: result = &dictionary[8]; break;
00682         case 0x1800: result = &dictionary[10]; break;
00683         case 0x1A00: result = &dictionary[11]; break;
00684         case 0x2001: result = &dictionary[12]; break;
00685         case 0x2002: result = &dictionary[13]; break;
00686         case 0x2100: result = &dictionary[14]; break;
00687         case 0x2200: result = &dictionary[15]; break;
00688         case 0x6000: result = &dictionary[16]; break;
00689         case 0x6005: result = &dictionary[17]; break;
00690         case 0x6006: result = &dictionary[18]; break;
00691         case 0x6200: result = &dictionary[19]; break;
00692         default:
00693             // TODO add error handling
00694             break;
00695     }
00696 
00697     return result;
00698 }
00699 
00700 } /* namespace ppCANOpen */