// (Re)Initialize the specified mode. // The mode parameter should be a value from enum DMXMode. void ModifiedDMXSerialClass::init (int mode, uint8_t* data) { stat = 0; #ifdef SCOPEDEBUG pinMode(DmxTriggerPin, OUTPUT); pinMode(DmxISRPin, OUTPUT); #endif _dmxData = data; // initialize global variables _dmxMode = DMXNone; _dmxRecvState= IDLE; // initial state _dmxChannel = 0; _gotLastPacket = millis(); // remember current (relative) time in msecs. // initialize the DMX buffer for (int n = 0; n < DMXSERIAL_MAX+1; n++) _dmxData[n] = 0; // now start _dmxMode = (DMXMode)mode; if (_dmxMode == DMXController) { // Setup external mode signal pinMode(DmxModePin, OUTPUT); // enables pin 2 for output to control data direction digitalWrite(DmxModePin, DmxModeOut); // data Out direction // Setup Hardware // Enable transmitter and interrupt UCSRnB = (1<<TXENn) | (1<<TXCIEn); // Start sending a BREAK and loop (forever) in UDRE ISR _DMXSerialBaud(Calcprescale(BREAKSPEED), BREAKFORMAT); _DMXSerialWriteByte((uint8_t)0); _dmxChannel = 0; } else if (_dmxMode == DMXReceiver) { // Setup external mode signal pinMode(DmxModePin, OUTPUT); // enables pin 2 for output to control data direction digitalWrite(DmxModePin, DmxModeIn); // data in direction // Setup Hardware // Enable receiver and Receive interrupt UCSRnB = (1<<RXENn) | (1<<RXCIEn); _DMXSerialBaud(Calcprescale(DMXSPEED), DMXFORMAT); // Enable serial reception with a 250k rate } else { // Enable receiver and transmitter and interrupts // UCSRnB = (1<<RXENn) | (1<<TXENn) | (1<<RXCIEn) | (1<<UDRIEn); } // if } // init()
// (Re)Initialize the specified mode. // The mode parameter should be a value from enum DMXMode. void ModifiedDMXSerialClass::init(int mode) { // Setup external mode signal //TODO Refactor to constant A0 is used as the RX/TX en pin on the RF1 Serial adapter pinMode(A0, OUTPUT); // enables pin 2 for output to control data direction digitalWrite(A0, LOW); //Set it low to put the RS485 chip in Receive mode #ifdef SCOPEDEBUG //if in debug mode define some pins for watching the timing in the logic analyzer pinMode(rxStatusPin, OUTPUT); // enables pin 2 for output to control data direction pinMode(DmxTriggerPin, OUTPUT); pinMode(DmxISRPin, OUTPUT); #endif // initialize global variables _dmxMode = DMXNone; _dmxRecvState = DMX_IDLE; // initial state _dmxChannel = 0; _gotLastPacket = millis(); // remember current (relative) time in msecs. // initialize the DMX buffer for (int n = 0; n < 18; n++){ for (int in = 0; in < 32; in++) str[n][in] = 0; } // now start _dmxMode = (DMXMode)mode; // Setup Hardware // Enable receiver and Receive interrupt UCSRnB = (1 << RXENn) | (1 << RXCIEn); _DMXSerialBaud(Calcprescale(DMXSPEED), DMXFORMAT); // Enable serial reception with a 250k rate } // init()
// Initialize or reinitialize the DMX RDM mode. // The other values are stored for later use with the specific commands. void DMXSerialClass2::init(struct RDMINIT *initData, RDMCallbackFunction func, uint8_t modePin, uint8_t modeIn, uint8_t modeOut) { // This structure is defined for mapping the values in the EEPROM struct EEPROMVALUES eeprom; // save the given initData for later use. _initData = initData; _rdmFunc = func; _dmxModePin = modePin; _dmxModeIn = modeIn; _dmxModeOut = modeOut; _baseInit(); // now initialize RDM specific elements _isMute = false; _rdmAvailable = false; _identifyMode = false; _softwareLabel = "Arduino RDM 1.0"; DeviceIDCpy(_devID, initData->deviceID); // read from EEPROM or set defaults for (unsigned int i = 0; i < sizeof(eeprom); i++) ((byte *)(&eeprom))[i] = EEPROM.read(i); // check if the EEEPROM values are from the RDM library if ((eeprom.sig1 == 0x6D) && (eeprom.sig2 == 0x68)) { _startAddress = eeprom.startAddress; strcpy (deviceLabel, eeprom.deviceLabel); DeviceIDCpy(_devID, eeprom.deviceID); } else { // set default values _startAddress = 1; strcpy (deviceLabel, "new"); _devID[4] = random255(); // random(255); _devID[5] = random255(); // random(255); } // if // setup the manufacturer adressing device-ID _devIDGroup[0] = _devID[0]; _devIDGroup[1] = _devID[1]; _saveEEPRom(); // now start digitalWrite(_dmxModePin, _dmxModeIn); // data in direction _dmxSendBuffer = _rdm.buffer; // _dmxSendLen = ... will be set individually // Setup Hardware // Enable receiver and transmitter and interrupts UCSRnB = (1<<RXENn) | (1<<RXCIEn); _DMXSerialBaud(Calcprescale(DMXSPEED), DMXFORMAT); // Enable serial reception with a 250k rate } // initRDM()
// Handle RDM Requests and send response // see http://www.opendmx.net/index.php/RDM_Discovery // see http://www.enttec.com/docs/sniffer_manual.pdf void DMXSerialClass2::tick(void) { if ((_dmxState == IDLE) && (_rdmAvailable)) { // never process twice. _rdmAvailable = false; // respond to RDM commands now. bool8 packetIsForMe = false; bool8 packetIsForGroup = false; bool8 packetIsForAll = false; bool8 isHandled = false; struct RDMDATA *rdm = &_rdm.packet; byte CmdClass = rdm->CmdClass; // command class uint16_t Parameter = rdm->Parameter; // parameter ID // in the ISR only some global conditions are checked: DestID if (DeviceIDCmp(rdm->DestID, _devIDAll) == 0) { packetIsForAll = true; } else if (DeviceIDCmp(rdm->DestID, _devIDGroup) == 0) { packetIsForGroup = true; } else if (DeviceIDCmp(rdm->DestID, _devID) == 0) { packetIsForMe = true; } // if if ((! packetIsForMe) && (! packetIsForGroup) && (! packetIsForAll)) { // ignore this packet } else if (CmdClass == E120_DISCOVERY_COMMAND) { // 0x10 // handle all Discovery commands locally if (Parameter == SWAPINT(E120_DISC_UNIQUE_BRANCH)) { // 0x0001 // not tested here for pgm space reasons: rdm->Length must be 24+6+6 = 36 // not tested here for pgm space reasons: rdm->_DataLength must be 6+6 = 12 if (! _isMute) { // check if my _devID is in the discovery range if ((DeviceIDCmp(rdm->Data, _devID) <= 0) && (DeviceIDCmp(_devID, rdm->Data+6) <= 0)) { // respond a special discovery message ! struct DISCOVERYMSG *disc = &_rdm.discovery; _rdmCheckSum = 6 * 0xFF; // fill in the _rdm.discovery response structure for (byte i = 0; i < 7; i++) disc->headerFE[i] = 0xFE; disc->headerAA = 0xAA; for (byte i = 0; i < 6; i++) { disc->maskedDevID[i+i] = _devID[i] | 0xAA; disc->maskedDevID[i+i+1] = _devID[i] | 0x55; _rdmCheckSum += _devID[i]; } disc->checksum[0] = (_rdmCheckSum >> 8) | 0xAA; disc->checksum[1] = (_rdmCheckSum >> 8) | 0x55; disc->checksum[2] = (_rdmCheckSum & 0xFF) | 0xAA; disc->checksum[3] = (_rdmCheckSum & 0xFF) | 0x55; // disable all interrupt routines and send the _rdm.discovery packet // now send out the _rdm.buffer without a starting BREAK. _DMXSerialBaud(Calcprescale(DMXSPEED), DMXFORMAT); UCSRnB = (1<<TXENn); // no interrupts ! // delayMicroseconds(50); // ??? 180 digitalWrite(_dmxModePin, _dmxModeOut); // data Out direction unsigned int _rdmBufferLen = sizeof(_rdm.discovery); for (unsigned int i = 0; i < _rdmBufferLen; i++) { UDRn = _rdm.buffer[i]; UCSRnA= (1<<TXCn); loop_until_bit_is_set(UCSRnA, TXCn); } // for digitalWrite(_dmxModePin, _dmxModeIn); // data Out direction // Re-enable receiver and Receive interrupt _dmxState= IDLE; // initial state UCSRnB = (1<<RXENn) | (1<<RXCIEn); _DMXSerialBaud(Calcprescale(DMXSPEED), DMXFORMAT); // Enable serial reception with a 250k rate } // if } // if } else if (Parameter == SWAPINT(E120_DISC_UN_MUTE)) { // 0x0003 isHandled = true; if (packetIsForMe) { // 05.12.2013 if (_rdm.packet.DataLength > 0) { // Unexpected data // Do nothing } else { _isMute = false; // Control field _rdm.packet.Data[0] = 0b00000000; _rdm.packet.Data[1] = 0b00000000; _rdm.packet.DataLength = 2; respondMessage(true); // 21.11.2013 } } } else if (Parameter == SWAPINT(E120_DISC_MUTE)) { // 0x0002 isHandled = true; if (packetIsForMe) { // 05.12.2013 if (_rdm.packet.DataLength > 0) { // Unexpected data // Do nothing } else { _isMute = true; // Control field _rdm.packet.Data[0] = 0b00000000; _rdm.packet.Data[1] = 0b00000000; _rdm.packet.DataLength = 2; respondMessage(true); // 21.11.2013 } } } // if } else {