Skip to content

Commit f670d95

Browse files
committed
added Conceptinetics library
1 parent 48f21c6 commit f670d95

File tree

13 files changed

+3457
-0
lines changed

13 files changed

+3457
-0
lines changed

DMX_NeoPixels/Conceptinetics/Conceptinetics.cpp

Lines changed: 1230 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 380 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,380 @@
1+
/*
2+
Conceptinetics.h - DMX library for Arduino
3+
Copyright (c) 2013 W.A. van der Meeren <danny@illogic.nl>. All right reserved.
4+
5+
This library is free software; you can redistribute it and/or
6+
modify it under the terms of the GNU Lesser General Public
7+
License as published by the Free Software Foundation; either
8+
version 3 of the License, or (at your option) any later version.
9+
10+
This library is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
Lesser General Public License for more details.
14+
15+
You should have received a copy of the GNU Lesser General Public
16+
License along with this library; if not, write to the Free Software
17+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18+
*/
19+
20+
/*
21+
This code has been tested using the following hardware:
22+
23+
- Arduino / Genuino UNO R3 using a CTC-DRA-13-1 ISOLATED DMX-RDM SHIELD
24+
- Arduino / Genuino MEGA2560 R3 using a CTC-DRA-13-1 ISOLATED DMX-RDM SHIELD
25+
- Arduino / Genuino Leonardo using a CTC-DRA-13-R2 ISOLATED DMX-RDM SHIELD
26+
27+
- CTC-DRA-10-1 and CTC-DRA-10-R2 is the Non-isolated costs effective DMX-RDM shield
28+
*/
29+
30+
31+
#ifndef CONCEPTINETICS_H_
32+
#define CONCEPTINETICS_H_
33+
34+
#include <Arduino.h>
35+
#include <inttypes.h>
36+
37+
#include "Rdm_Uid.h"
38+
#include "Rdm_Defines.h"
39+
40+
#define DMX_MAX_FRAMESIZE 513 // Startbyte + 512 Slots
41+
#define DMX_MIN_FRAMESIZE 2 // Startbyte + 1 Slot
42+
43+
#define DMX_MAX_FRAMECHANNELS 512 // Maxmim number of channer per frame
44+
45+
#define DMX_STARTCODE_SIZE 1 // Size of startcode in bytes
46+
47+
#define DMX_START_CODE 0x0 // Start code for a DMX frame
48+
#define RDM_START_CODE 0xcc // Start code for a RDM frame
49+
50+
// Uncomment to enable Inter slot delay ) (avg < 76uSec) ...
51+
// mimum is zero according to specification
52+
// #define DMX_IBG 10 // Inter slot time
53+
54+
// Speed your Arduino is running on in Hz.
55+
#define F_OSC 16000000UL
56+
57+
// DMX Baudrate, this should be 250000
58+
#define DMX_BAUD_RATE 250000
59+
60+
// The baudrate used to automaticly generate a break within
61+
// your ISR.. make it lower to generate longer breaks
62+
//#define DMX_BREAK_RATE 99900
63+
64+
// 2017, Feb 28: Set to appox 176us
65+
#define DMX_BREAK_RATE 49950
66+
67+
// Tabel 3-2 ANSI_E1-20-2010
68+
// Minimum time to allow the datalink to 'turn arround'
69+
#define MIN_RESPONDER_PACKET_SPACING_USEC 176 /*176*/
70+
71+
// Define which serial port to use as DMX port, only one can be
72+
// selected at the time by uncommenting one of the following
73+
// lines
74+
#define USE_DMX_SERIAL_0
75+
//#define USE_DMX_SERIAL_1
76+
//#define USE_DMX_SERIAL_2
77+
//#define USE_DMX_SERIAL_3
78+
79+
namespace dmx
80+
{
81+
enum dmxState
82+
{
83+
dmxUnknown,
84+
dmxStartByte,
85+
dmxWaitStartAddress,
86+
dmxData,
87+
dmxFrameReady,
88+
};
89+
};
90+
91+
namespace rdm
92+
{
93+
enum rdmState
94+
{
95+
rdmUnknown,
96+
rdmStartByte,
97+
rdmSubStartCode,
98+
rdmMessageLength,
99+
rdmData,
100+
rdmChecksumHigh,
101+
rdmChecksumLow,
102+
rdmFrameReady,
103+
};
104+
};
105+
106+
struct IFrameBuffer
107+
{
108+
virtual uint16_t getBufferSize ( void ) = 0;
109+
110+
virtual uint8_t getSlotValue ( uint16_t index ) = 0;
111+
virtual void setSlotValue ( uint16_t index, uint8_t value ) = 0;
112+
};
113+
114+
class DMX_FrameBuffer : IFrameBuffer
115+
{
116+
public:
117+
//
118+
// Constructor buffersize = 1-513
119+
//
120+
DMX_FrameBuffer ( uint16_t buffer_size );
121+
DMX_FrameBuffer ( DMX_FrameBuffer &buffer );
122+
~DMX_FrameBuffer ( void );
123+
124+
uint16_t getBufferSize ( void );
125+
126+
uint8_t getSlotValue ( uint16_t index );
127+
void setSlotValue ( uint16_t index, uint8_t value );
128+
void setSlotRange ( uint16_t start, uint16_t end, uint8_t value );
129+
void clear ( void );
130+
131+
uint8_t &operator[] ( uint16_t index );
132+
133+
private:
134+
135+
uint8_t *m_refcount;
136+
uint16_t m_bufferSize;
137+
uint8_t *m_buffer;
138+
};
139+
140+
141+
//
142+
// DMX Master controller
143+
//
144+
class DMX_Master
145+
{
146+
public:
147+
// Run the DMX master from a pre allocated frame buffer which
148+
// you have fully under your own control
149+
DMX_Master ( DMX_FrameBuffer &buffer, int readEnablePin );
150+
151+
// Run the DMX master by giving a predefined maximum number of
152+
// channels to support
153+
DMX_Master ( uint16_t maxChannel, int readEnablePin );
154+
155+
~DMX_Master ( void );
156+
157+
void enable ( void ); // Start transmitting
158+
void disable ( void ); // Stop transmitting
159+
160+
// Get reference to the internal framebuffer
161+
DMX_FrameBuffer &getBuffer ( void );
162+
163+
// Update channel values
164+
void setChannelValue ( uint16_t channel, uint8_t value );
165+
void setChannelRange ( uint16_t start, uint16_t end, uint8_t value );
166+
167+
public:
168+
//
169+
// Manual control over the break period
170+
//
171+
void setAutoBreakMode ( void ); // Generated from ISR
172+
void setManualBreakMode ( void ); // Generate manually
173+
174+
uint8_t autoBreakEnabled ( void );
175+
176+
// We are waiting for a manual break to be generated
177+
uint8_t waitingBreak ( void );
178+
179+
// Generate break and start transmission of frame
180+
void breakAndContinue ( uint8_t breakLength_us = 100 );
181+
182+
183+
protected:
184+
void setStartCode ( uint8_t value );
185+
186+
187+
private:
188+
DMX_FrameBuffer m_frameBuffer;
189+
uint8_t m_autoBreak;
190+
};
191+
192+
193+
//
194+
// DMX Slave controller
195+
//
196+
class DMX_Slave : public DMX_FrameBuffer
197+
{
198+
public:
199+
DMX_Slave ( DMX_FrameBuffer &buffer, int readEnablePin = -1 );
200+
201+
// nrChannels is the consecutive DMX512 slots required
202+
// to operate this slave device
203+
DMX_Slave ( uint16_t nrChannels, int readEnablePin = -1 );
204+
205+
~DMX_Slave ( void );
206+
207+
void enable ( void ); // Enable receiver
208+
void disable ( void ); // Disable receiver
209+
210+
211+
// Get reference to the internal framebuffer
212+
DMX_FrameBuffer &getBuffer ( void );
213+
214+
uint8_t getChannelValue ( uint16_t channel );
215+
216+
uint16_t getStartAddress ( void );
217+
void setStartAddress ( uint16_t );
218+
219+
220+
// Process incoming byte from USART
221+
bool processIncoming ( uint8_t val, bool first = false );
222+
223+
// Register on receive complete callback in case
224+
// of time critical applications
225+
void onReceiveComplete ( void (*func)(unsigned short) );
226+
227+
protected:
228+
229+
230+
private:
231+
uint16_t m_startAddress; // Slave start address
232+
dmx::dmxState m_state;
233+
234+
static void (*event_onFrameReceived)(unsigned short channelsReceived);
235+
};
236+
237+
238+
class RDM_FrameBuffer : public IFrameBuffer
239+
{
240+
public:
241+
//
242+
// Constructor
243+
//
244+
RDM_FrameBuffer ( void ) {};
245+
~RDM_FrameBuffer ( void ) {};
246+
247+
uint16_t getBufferSize ( void );
248+
249+
uint8_t getSlotValue ( uint16_t index );
250+
void setSlotValue ( uint16_t index, uint8_t value );
251+
void clear ( void );
252+
253+
uint8_t &operator[] ( uint16_t index );
254+
255+
public: // functions to provide access from USART
256+
// Process incoming byte from USART,
257+
// returns false when no more data is accepted
258+
bool processIncoming ( uint8_t val, bool first = false );
259+
260+
// Process outgoing byte to USART
261+
// returns false when no more data is available
262+
bool fetchOutgoing ( volatile uint8_t *udr, bool first = false );
263+
264+
protected:
265+
// Process received frame
266+
virtual void processFrame ( void ) = 0;
267+
268+
//private:
269+
protected:
270+
rdm::rdmState m_state; // State for pushing the message in
271+
RDM_Message m_msg;
272+
RDM_Checksum m_csRecv; // Checksum received in rdm message
273+
};
274+
275+
//
276+
// RDM_Responder
277+
//
278+
class RDM_Responder : public RDM_FrameBuffer
279+
{
280+
public:
281+
//
282+
// m = manufacturer id (16bits)
283+
// d1-d4 = device id (32bits)
284+
//
285+
RDM_Responder ( uint16_t m, uint8_t d1, uint8_t d2, uint8_t d3, uint8_t d4, DMX_Slave &slave);
286+
~RDM_Responder ( void );
287+
288+
void setDeviceInfo
289+
(
290+
uint16_t deviceModelId,
291+
rdm::RdmProductCategory productCategory,
292+
uint8_t personalities = 1,
293+
uint8_t personality = 1
294+
)
295+
{
296+
m_DeviceModelId = deviceModelId;
297+
m_ProductCategory = productCategory;
298+
m_Personalities = personalities;
299+
m_Personality = personality;
300+
};
301+
302+
//
303+
// Set vendor software version id
304+
//
305+
// v1 = MOST SIGNIFICANT
306+
// v2...
307+
// v3...
308+
// v4 = LEAST SIGNIFICANT
309+
//
310+
void setSoftwareVersionId ( uint8_t v1, uint8_t v2, uint8_t v3, uint8_t v4 )
311+
{
312+
m_SoftwareVersionId[0] = v1;
313+
m_SoftwareVersionId[1] = v2;
314+
m_SoftwareVersionId[2] = v3;
315+
m_SoftwareVersionId[3] = v4;
316+
}
317+
318+
// Currently no sensors and subdevices supported
319+
// void AddSensor ( void );
320+
// void AddSubDevice ( void );
321+
322+
uint8_t getPersonality ( void ) { return m_Personality; };
323+
void setPersonality ( uint8_t personality ) { m_Personality = personality; };
324+
325+
// Register on identify device event handler
326+
void onIdentifyDevice ( void (*func)(bool) );
327+
void onDeviceLabelChanged ( void (*func) (const char*, uint8_t) );
328+
void onDMXStartAddressChanged ( void (*func) (uint16_t) );
329+
void onDMXPersonalityChanged ( void (*func) (uint8_t) );
330+
331+
332+
// Set the device label
333+
void setDeviceLabel ( const char *label, size_t len );
334+
335+
// Enable, Disable rdm responder
336+
void enable ( void ) { m_rdmStatus.enabled = true; m_rdmStatus.mute = false; };
337+
void disable ( void ) { m_rdmStatus.enabled = false; };
338+
339+
union
340+
{
341+
uint8_t raw;
342+
struct
343+
{
344+
uint8_t mute:1;
345+
uint8_t ident:1;
346+
uint8_t enabled:1; // Rdm responder enable/disable
347+
};
348+
} m_rdmStatus;
349+
350+
351+
protected:
352+
virtual void processFrame ( void );
353+
354+
// Discovery to unque brach packets only requires
355+
// the data part of the packet to be transmitted
356+
// without breaks or header
357+
void repondDiscUniqueBranch ( void );
358+
359+
// Helpers for generating response packets which
360+
// have larger datafields
361+
void populateDeviceInfo ( void );
362+
363+
private:
364+
RDM_Uid m_devid; // Holds our unique device ID
365+
uint8_t m_Personalities; // The total number of supported personalities
366+
uint8_t m_Personality; // The currently active personality
367+
uint16_t m_DeviceModelId;
368+
uint8_t m_SoftwareVersionId[4]; // 32 bit Software version
369+
rdm::RdmProductCategory m_ProductCategory;
370+
371+
char m_deviceLabel[32]; // Device label
372+
373+
static void (*event_onIdentifyDevice)(bool);
374+
static void (*event_onDeviceLabelChanged)(const char*, uint8_t);
375+
static void (*event_onDMXStartAddressChanged)(uint16_t);
376+
static void (*event_onDMXPersonalityChanged)(uint8_t);
377+
};
378+
379+
380+
#endif /* CONCEPTINETICS_H_ */

0 commit comments

Comments
 (0)