Lab_interaccio/2009/DMX_CONTROLv2a/applet/DMX_CONTROLv2a.cpp

206 lines
4.4 KiB
C++
Raw Normal View History

2025-02-25 21:21:58 +01:00
#include "pins_arduino.h"
#include "WProgram.h"
void setDmxChannel(byte channelID, byte value);
void shiftDmxOut(int pin, int theByte);
void processDmx();
void setup();
void loop();
int sig = 8; // signal para mochila
//int sig = 5; // signal para placa integrada
int value = 0;
int value1 = 0;
int value2 = 0;
int value3 = 0;
int i=0;
int e=0;
byte checksum;
byte id=0;
int valueadd = 3;
byte buffer[10];
byte color[256];
byte dmxChannel[64];
void setDmxChannel(byte channelID, byte value) {
if (channelID < 64)
dmxChannel[channelID] = value;
}
/* Sends a DMX byte out on a pin. Assumes a 16 MHz clock.
* Disables interrupts, which will disrupt the millis() function if used
* too frequently. */
void shiftDmxOut(int pin, int theByte)
{
int port_to_output[] = {
NOT_A_PORT,
NOT_A_PORT,
_SFR_IO_ADDR(PORTB),
_SFR_IO_ADDR(PORTC),
_SFR_IO_ADDR(PORTD)
};
int portNumber = port_to_output[digitalPinToPort(pin)];
int pinMask = digitalPinToBitMask(pin);
// the first thing we do is to write te pin to high
// it will be the mark between bytes. It may be also
// high from before
_SFR_BYTE(_SFR_IO8(portNumber)) |= pinMask;
delayMicroseconds(10);
// disable interrupts, otherwise the timer 0 overflow interrupt that
// tracks milliseconds will make us delay longer than we want.
cli();
// DMX starts with a start-bit that must always be zero
_SFR_BYTE(_SFR_IO8(portNumber)) &= ~pinMask;
// we need a delay of 4us (then one bit is transfered)
// this seems more stable then using delayMicroseconds
asm("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n");
asm("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n");
asm("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n");
asm("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n");
asm("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n");
asm("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n");
for (int i = 0; i < 8; i++)
{
if (theByte & 01)
{
_SFR_BYTE(_SFR_IO8(portNumber)) |= pinMask;
}
else
{
_SFR_BYTE(_SFR_IO8(portNumber)) &= ~pinMask;
}
asm("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n");
asm("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n");
asm("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n");
asm("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n");
asm("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n");
asm("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n");
theByte >>= 1;
}
// the last thing we do is to write the pin to high
// it will be the mark between bytes. (this break is have to be between 8 us and 1 sec)
_SFR_BYTE(_SFR_IO8(portNumber)) |= pinMask;
// reenable interrupts.
sei();
}
void processDmx() {
/***** sending the dmx signal *****/
// sending the break (the break can be between 88us and 1sec)
digitalWrite(sig, LOW);
delayMicroseconds(100);
dmxChannel[0] = 0;
for (int count = 0; count <= 64; count++)
{
if (count < 64)
shiftDmxOut(sig, dmxChannel[count]);
else
shiftDmxOut(sig,0);
}
/***** sending the dmx signal end *****/
}
void setup()
{
Serial.begin(57600);
delay(100);
pinMode(sig, OUTPUT);
}
void loop()
{
if (Serial.available()) {
value = Serial.read();
if ((0xD9 == value)&&(i==0))
{
i=1;
}
else if (i==1)
{
id=value;
i=2;
}
else if ((i>=2)&&(i<6))
{
buffer[i]=value;
i=i+1;
}
if (i==6)
{
i=0;
checksum = (buffer[2]+buffer[3]+buffer[4]);
if ( buffer[5] == checksum ) //CHECKSUM (8 bits menos significativos)
{
if (id==0)
{
color[0] = buffer[2];
color[1] = buffer[3];
color[2] = buffer[4];
}
else
{
color[id*3+1] = buffer[2];
color[id*3+2] = buffer[3];
color[id*3+3] = buffer[4];
}
}
else
{
Serial.print(id ,BYTE);
Serial.print(buffer[2] ,BYTE);
Serial.print(buffer[3] ,BYTE);
Serial.print(buffer[4] ,BYTE);
Serial.print(buffer[5] ,BYTE);
Serial.print(checksum ,BYTE);
}
}
}
if (i==0)
{
if (id==0) for (e=0; e<=2; e++) setDmxChannel(e,color[e]);
else for (e=id*3+1; e<=id*3+3; e++) setDmxChannel(e,color[e]);
processDmx();
}
}
int main(void)
{
init();
setup();
for (;;)
loop();
return 0;
}