-
Notifications
You must be signed in to change notification settings - Fork 775
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2939 from jedgarpark/dmx-neopixels
first commit DMX NeoPixel code
- Loading branch information
Showing
291 changed files
with
3,866 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,383 @@ | ||
// SPDX-FileCopyrightText: 2013 W.A. van der Meeren <[email protected]> | ||
// | ||
// SPDX-License-Identifier: LGPL-3.0-or-later | ||
/* | ||
Conceptinetics.h - DMX library for Arduino | ||
Copyright (c) 2013 W.A. van der Meeren <[email protected]>. All right reserved. | ||
This library is free software; you can redistribute it and/or | ||
modify it under the terms of the GNU Lesser General Public | ||
License as published by the Free Software Foundation; either | ||
version 3 of the License, or (at your option) any later version. | ||
This library 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 | ||
Lesser General Public License for more details. | ||
You should have received a copy of the GNU Lesser General Public | ||
License along with this library; if not, write to the Free Software | ||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
*/ | ||
|
||
/* | ||
This code has been tested using the following hardware: | ||
- Arduino / Genuino UNO R3 using a CTC-DRA-13-1 ISOLATED DMX-RDM SHIELD | ||
- Arduino / Genuino MEGA2560 R3 using a CTC-DRA-13-1 ISOLATED DMX-RDM SHIELD | ||
- Arduino / Genuino Leonardo using a CTC-DRA-13-R2 ISOLATED DMX-RDM SHIELD | ||
- CTC-DRA-10-1 and CTC-DRA-10-R2 is the Non-isolated costs effective DMX-RDM shield | ||
*/ | ||
|
||
|
||
#ifndef CONCEPTINETICS_H_ | ||
#define CONCEPTINETICS_H_ | ||
|
||
#include <Arduino.h> | ||
#include <inttypes.h> | ||
|
||
#include "Rdm_Uid.h" | ||
#include "Rdm_Defines.h" | ||
|
||
#define DMX_MAX_FRAMESIZE 513 // Startbyte + 512 Slots | ||
#define DMX_MIN_FRAMESIZE 2 // Startbyte + 1 Slot | ||
|
||
#define DMX_MAX_FRAMECHANNELS 512 // Maxmim number of channer per frame | ||
|
||
#define DMX_STARTCODE_SIZE 1 // Size of startcode in bytes | ||
|
||
#define DMX_START_CODE 0x0 // Start code for a DMX frame | ||
#define RDM_START_CODE 0xcc // Start code for a RDM frame | ||
|
||
// Uncomment to enable Inter slot delay ) (avg < 76uSec) ... | ||
// mimum is zero according to specification | ||
// #define DMX_IBG 10 // Inter slot time | ||
|
||
// Speed your Arduino is running on in Hz. | ||
#define F_OSC 16000000UL | ||
|
||
// DMX Baudrate, this should be 250000 | ||
#define DMX_BAUD_RATE 250000 | ||
|
||
// The baudrate used to automaticly generate a break within | ||
// your ISR.. make it lower to generate longer breaks | ||
//#define DMX_BREAK_RATE 99900 | ||
|
||
// 2017, Feb 28: Set to appox 176us | ||
#define DMX_BREAK_RATE 49950 | ||
|
||
// Tabel 3-2 ANSI_E1-20-2010 | ||
// Minimum time to allow the datalink to 'turn arround' | ||
#define MIN_RESPONDER_PACKET_SPACING_USEC 176 /*176*/ | ||
|
||
// Define which serial port to use as DMX port, only one can be | ||
// selected at the time by uncommenting one of the following | ||
// lines | ||
#define USE_DMX_SERIAL_0 | ||
//#define USE_DMX_SERIAL_1 | ||
//#define USE_DMX_SERIAL_2 | ||
//#define USE_DMX_SERIAL_3 | ||
|
||
namespace dmx | ||
{ | ||
enum dmxState | ||
{ | ||
dmxUnknown, | ||
dmxStartByte, | ||
dmxWaitStartAddress, | ||
dmxData, | ||
dmxFrameReady, | ||
}; | ||
}; | ||
|
||
namespace rdm | ||
{ | ||
enum rdmState | ||
{ | ||
rdmUnknown, | ||
rdmStartByte, | ||
rdmSubStartCode, | ||
rdmMessageLength, | ||
rdmData, | ||
rdmChecksumHigh, | ||
rdmChecksumLow, | ||
rdmFrameReady, | ||
}; | ||
}; | ||
|
||
struct IFrameBuffer | ||
{ | ||
virtual uint16_t getBufferSize ( void ) = 0; | ||
|
||
virtual uint8_t getSlotValue ( uint16_t index ) = 0; | ||
virtual void setSlotValue ( uint16_t index, uint8_t value ) = 0; | ||
}; | ||
|
||
class DMX_FrameBuffer : IFrameBuffer | ||
{ | ||
public: | ||
// | ||
// Constructor buffersize = 1-513 | ||
// | ||
DMX_FrameBuffer ( uint16_t buffer_size ); | ||
DMX_FrameBuffer ( DMX_FrameBuffer &buffer ); | ||
~DMX_FrameBuffer ( void ); | ||
|
||
uint16_t getBufferSize ( void ); | ||
|
||
uint8_t getSlotValue ( uint16_t index ); | ||
void setSlotValue ( uint16_t index, uint8_t value ); | ||
void setSlotRange ( uint16_t start, uint16_t end, uint8_t value ); | ||
void clear ( void ); | ||
|
||
uint8_t &operator[] ( uint16_t index ); | ||
|
||
private: | ||
|
||
uint8_t *m_refcount; | ||
uint16_t m_bufferSize; | ||
uint8_t *m_buffer; | ||
}; | ||
|
||
|
||
// | ||
// DMX Master controller | ||
// | ||
class DMX_Master | ||
{ | ||
public: | ||
// Run the DMX master from a pre allocated frame buffer which | ||
// you have fully under your own control | ||
DMX_Master ( DMX_FrameBuffer &buffer, int readEnablePin ); | ||
|
||
// Run the DMX master by giving a predefined maximum number of | ||
// channels to support | ||
DMX_Master ( uint16_t maxChannel, int readEnablePin ); | ||
|
||
~DMX_Master ( void ); | ||
|
||
void enable ( void ); // Start transmitting | ||
void disable ( void ); // Stop transmitting | ||
|
||
// Get reference to the internal framebuffer | ||
DMX_FrameBuffer &getBuffer ( void ); | ||
|
||
// Update channel values | ||
void setChannelValue ( uint16_t channel, uint8_t value ); | ||
void setChannelRange ( uint16_t start, uint16_t end, uint8_t value ); | ||
|
||
public: | ||
// | ||
// Manual control over the break period | ||
// | ||
void setAutoBreakMode ( void ); // Generated from ISR | ||
void setManualBreakMode ( void ); // Generate manually | ||
|
||
uint8_t autoBreakEnabled ( void ); | ||
|
||
// We are waiting for a manual break to be generated | ||
uint8_t waitingBreak ( void ); | ||
|
||
// Generate break and start transmission of frame | ||
void breakAndContinue ( uint8_t breakLength_us = 100 ); | ||
|
||
|
||
protected: | ||
void setStartCode ( uint8_t value ); | ||
|
||
|
||
private: | ||
DMX_FrameBuffer m_frameBuffer; | ||
uint8_t m_autoBreak; | ||
}; | ||
|
||
|
||
// | ||
// DMX Slave controller | ||
// | ||
class DMX_Slave : public DMX_FrameBuffer | ||
{ | ||
public: | ||
DMX_Slave ( DMX_FrameBuffer &buffer, int readEnablePin = -1 ); | ||
|
||
// nrChannels is the consecutive DMX512 slots required | ||
// to operate this slave device | ||
DMX_Slave ( uint16_t nrChannels, int readEnablePin = -1 ); | ||
|
||
~DMX_Slave ( void ); | ||
|
||
void enable ( void ); // Enable receiver | ||
void disable ( void ); // Disable receiver | ||
|
||
|
||
// Get reference to the internal framebuffer | ||
DMX_FrameBuffer &getBuffer ( void ); | ||
|
||
uint8_t getChannelValue ( uint16_t channel ); | ||
|
||
uint16_t getStartAddress ( void ); | ||
void setStartAddress ( uint16_t ); | ||
|
||
|
||
// Process incoming byte from USART | ||
bool processIncoming ( uint8_t val, bool first = false ); | ||
|
||
// Register on receive complete callback in case | ||
// of time critical applications | ||
void onReceiveComplete ( void (*func)(unsigned short) ); | ||
|
||
protected: | ||
|
||
|
||
private: | ||
uint16_t m_startAddress; // Slave start address | ||
dmx::dmxState m_state; | ||
|
||
static void (*event_onFrameReceived)(unsigned short channelsReceived); | ||
}; | ||
|
||
|
||
class RDM_FrameBuffer : public IFrameBuffer | ||
{ | ||
public: | ||
// | ||
// Constructor | ||
// | ||
RDM_FrameBuffer ( void ) {}; | ||
~RDM_FrameBuffer ( void ) {}; | ||
|
||
uint16_t getBufferSize ( void ); | ||
|
||
uint8_t getSlotValue ( uint16_t index ); | ||
void setSlotValue ( uint16_t index, uint8_t value ); | ||
void clear ( void ); | ||
|
||
uint8_t &operator[] ( uint16_t index ); | ||
|
||
public: // functions to provide access from USART | ||
// Process incoming byte from USART, | ||
// returns false when no more data is accepted | ||
bool processIncoming ( uint8_t val, bool first = false ); | ||
|
||
// Process outgoing byte to USART | ||
// returns false when no more data is available | ||
bool fetchOutgoing ( volatile uint8_t *udr, bool first = false ); | ||
|
||
protected: | ||
// Process received frame | ||
virtual void processFrame ( void ) = 0; | ||
|
||
//private: | ||
protected: | ||
rdm::rdmState m_state; // State for pushing the message in | ||
RDM_Message m_msg; | ||
RDM_Checksum m_csRecv; // Checksum received in rdm message | ||
}; | ||
|
||
// | ||
// RDM_Responder | ||
// | ||
class RDM_Responder : public RDM_FrameBuffer | ||
{ | ||
public: | ||
// | ||
// m = manufacturer id (16bits) | ||
// d1-d4 = device id (32bits) | ||
// | ||
RDM_Responder ( uint16_t m, uint8_t d1, uint8_t d2, uint8_t d3, uint8_t d4, DMX_Slave &slave); | ||
~RDM_Responder ( void ); | ||
|
||
void setDeviceInfo | ||
( | ||
uint16_t deviceModelId, | ||
rdm::RdmProductCategory productCategory, | ||
uint8_t personalities = 1, | ||
uint8_t personality = 1 | ||
) | ||
{ | ||
m_DeviceModelId = deviceModelId; | ||
m_ProductCategory = productCategory; | ||
m_Personalities = personalities; | ||
m_Personality = personality; | ||
}; | ||
|
||
// | ||
// Set vendor software version id | ||
// | ||
// v1 = MOST SIGNIFICANT | ||
// v2... | ||
// v3... | ||
// v4 = LEAST SIGNIFICANT | ||
// | ||
void setSoftwareVersionId ( uint8_t v1, uint8_t v2, uint8_t v3, uint8_t v4 ) | ||
{ | ||
m_SoftwareVersionId[0] = v1; | ||
m_SoftwareVersionId[1] = v2; | ||
m_SoftwareVersionId[2] = v3; | ||
m_SoftwareVersionId[3] = v4; | ||
} | ||
|
||
// Currently no sensors and subdevices supported | ||
// void AddSensor ( void ); | ||
// void AddSubDevice ( void ); | ||
|
||
uint8_t getPersonality ( void ) { return m_Personality; }; | ||
void setPersonality ( uint8_t personality ) { m_Personality = personality; }; | ||
|
||
// Register on identify device event handler | ||
void onIdentifyDevice ( void (*func)(bool) ); | ||
void onDeviceLabelChanged ( void (*func) (const char*, uint8_t) ); | ||
void onDMXStartAddressChanged ( void (*func) (uint16_t) ); | ||
void onDMXPersonalityChanged ( void (*func) (uint8_t) ); | ||
|
||
|
||
// Set the device label | ||
void setDeviceLabel ( const char *label, size_t len ); | ||
|
||
// Enable, Disable rdm responder | ||
void enable ( void ) { m_rdmStatus.enabled = true; m_rdmStatus.mute = false; }; | ||
void disable ( void ) { m_rdmStatus.enabled = false; }; | ||
|
||
union | ||
{ | ||
uint8_t raw; | ||
struct | ||
{ | ||
uint8_t mute:1; | ||
uint8_t ident:1; | ||
uint8_t enabled:1; // Rdm responder enable/disable | ||
}; | ||
} m_rdmStatus; | ||
|
||
|
||
protected: | ||
virtual void processFrame ( void ); | ||
|
||
// Discovery to unque brach packets only requires | ||
// the data part of the packet to be transmitted | ||
// without breaks or header | ||
void repondDiscUniqueBranch ( void ); | ||
|
||
// Helpers for generating response packets which | ||
// have larger datafields | ||
void populateDeviceInfo ( void ); | ||
|
||
private: | ||
RDM_Uid m_devid; // Holds our unique device ID | ||
uint8_t m_Personalities; // The total number of supported personalities | ||
uint8_t m_Personality; // The currently active personality | ||
uint16_t m_DeviceModelId; | ||
uint8_t m_SoftwareVersionId[4]; // 32 bit Software version | ||
rdm::RdmProductCategory m_ProductCategory; | ||
|
||
char m_deviceLabel[32]; // Device label | ||
|
||
static void (*event_onIdentifyDevice)(bool); | ||
static void (*event_onDeviceLabelChanged)(const char*, uint8_t); | ||
static void (*event_onDMXStartAddressChanged)(uint16_t); | ||
static void (*event_onDMXPersonalityChanged)(uint8_t); | ||
}; | ||
|
||
|
||
#endif /* CONCEPTINETICS_H_ */ |
Oops, something went wrong.