Skip to content

Commit 9fb7571

Browse files
author
Tim Essig
committed
WIP: Web interface, UPDATED Readme.md
1 parent 280eeff commit 9fb7571

23 files changed

+304
-58
lines changed

.gitignore

+3-1
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,6 @@
55
*.eep
66
*.sym
77
obj/**
8-
.dep/**
8+
.dep/**
9+
10+
.directory

EtherCard.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
//
1010
// 2010-05-19 <jc@wippler.nl>
1111

12-
#include "ethercard.h"
12+
#include "EtherCard.h"
1313
#include <stdarg.h>
1414
#include <avr/eeprom.h>
1515
#include <stdlib.h>

ethercard.h renamed to EtherCard.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,14 @@
4242
* still compile but the program will not work. Saves about 60 bytes SRAM and
4343
* 1550 bytes flash.
4444
*/
45-
#define ETHERCARD_DHCP 1
45+
#define ETHERCARD_DHCP 0
4646

4747
/** Enable client connections.
4848
* Setting this to zero means that the program cannot issue TCP client requests
4949
* anymore. Compilation will still work but the request will never be
5050
* issued. Saves 4 bytes SRAM and 550 byte flash.
5151
*/
52-
#define ETHERCARD_TCPCLIENT 1
52+
#define ETHERCARD_TCPCLIENT 0
5353

5454
/** Enable TCP server functionality.
5555
* Setting this to zero means that the program will not accept TCP client

README.md

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
2+
# ArtNetNode 4
3+
4+
Small Xmega32 and enc28j60 based DYI ArtNet Node with 4 DMX ports.
5+
6+
## Features:
7+
- 4 DMX Outputs(full 512 channels)
8+
- Testes framerate: 4x 52 FPS
9+
- Web Interface for configuration(WIP, see TODO)
10+
- industry standard 19" 1U housing
11+
12+
13+
## TODO:
14+
- [ ] Finish WebInterface
15+
- [ ] Persist Settings(Name, IP, Universes)
16+
- [ ] Use DMX Ports as Input
17+
- [ ] Implement ArtPoolReplay
18+
- [ ] Implement other ArtNet functions(setName,...)
19+
20+
21+
## Images
22+
23+
![First Prototype](images/ArtNetNode_Prototype_1.jpeg "First Prototype")
24+
First Prototype
25+
26+
![PCB](images/ArtNetNode_PCB.jpeg "PCB")
27+
Fresh PCB's
28+
29+
![Soldered PCB's](images/ArtNetNode_Prototype_2.jpeg "Soldered PCB's")
30+
Soldered PCB's
31+
32+
![Mounted front plate](images/ArtNetNode_Front1.jpeg "Mounted front plate")
33+
Mounted front plate
34+
35+
![Full Housing](images/ArtNetNode_FullHousing.jpeg "Full Housing")
36+
Full Housing
37+
38+
39+

artnet.cpp

+147-3
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,171 @@
11
#include "artnet.h"
22
#include "dmx.h"
3+
#include "EtherCard.h"
4+
5+
#include <string.h> //memcpy
36

47

58
volatile uint8_t universeFPS[DMX_NUM_UNIVERSES];
69
volatile uint8_t universeFPSCounter[DMX_NUM_UNIVERSES] = {0};
710

8-
uint8_t getUniverseFPS(uint8_t universe) {
11+
ArtNet artnet; //Global instance of ArtNet class
12+
13+
// Opcodes
14+
#define ART_POLL 0x2000
15+
#define ART_POLL_REPLAY 0x2100
16+
#define ART_DMX 0x5000
17+
// Buffers
18+
#define MAX_BUFFER_ARTNET 530
19+
// Packet
20+
#define ART_NET_ID "Art-Net\0"
21+
22+
23+
24+
/**
25+
* Receive ArtNet Packages from Ethercard
26+
*
27+
*
28+
**/
29+
void ArtNet::udpArtNet(uint16_t dest_port, uint8_t src_ip[IP_LEN], uint16_t src_port, const char *data, uint16_t len) {
30+
uint8_t result = strncmp(data, "Art-Net",7);
31+
32+
uint16_t opCode = (data[9] << 8) | data[8];
33+
uint16_t protocolVersion = data[10] << 8 | data[11];
34+
35+
uint16_t universe = data[14] | data[15] << 8 ;
36+
uint16_t length = data[16] << 8 | data[17];
37+
38+
39+
if(opCode == ART_POLL) {
40+
PORTA.OUTTGL = 0x02;
41+
sendArtPollReplay();
42+
} else if(opCode == ART_DMX) {
43+
if (universe < 4) {
44+
memcpy(dmxBuffer[universe], data + 18, length);
45+
universeReceivedTMP(universe);
46+
}
47+
}
48+
}
49+
50+
uint8_t ArtNet::getUniverseFPS(uint8_t universe) {
951
if(universe < DMX_NUM_UNIVERSES) {
1052
return universeFPS[universe];
1153
} else {
1254
return 0;
1355
}
1456
}
1557

16-
void universeReceivedTMP(uint8_t universe) {
58+
void ArtNet::universeReceivedTMP(uint8_t universe) {
1759
if(universe < DMX_NUM_UNIVERSES) {
1860
universeFPSCounter[universe]++;
1961
}
2062
}
2163

22-
void doTimerStuff1Hz(void) {
64+
void ArtNet::doTimerStuff1Hz(void) {
2365
for(uint8_t i=0; i < 4; i++) {
2466
universeFPS[i] = universeFPSCounter[i];
2567
universeFPSCounter[i] = 0;
2668
}
69+
}
70+
71+
void ArtNet::sendArtPollReplay(void) {
72+
//Build ArtPollReplay Package
73+
struct ArtPollReplay_t {
74+
uint8_t id[8];
75+
uint8_t opCode[2];
76+
uint8_t ipAddress[4];
77+
uint8_t port[2];
78+
uint8_t versInfoH;
79+
uint8_t versInfoL;
80+
uint8_t netSwitch;
81+
uint8_t subSwitch;
82+
uint8_t oemHi;
83+
uint8_t oem;
84+
uint8_t ubeaVersion;
85+
uint8_t status1;
86+
uint8_t estaManLo;
87+
uint8_t estaManHi;
88+
uint8_t shortName[18];
89+
uint8_t longName[64];
90+
uint8_t nodeReport[64];
91+
uint8_t numPortsHi;
92+
uint8_t numPortsLo;
93+
uint8_t portTypes[4];
94+
uint8_t goodInput[4];
95+
uint8_t goodOutput[4];
96+
uint8_t swIn[4];
97+
uint8_t swOut[4];
98+
uint8_t swVideo;
99+
uint8_t swMacro;
100+
uint8_t swRemote;
101+
uint8_t spare[3];
102+
uint8_t style;
103+
uint8_t mac[6];
104+
uint8_t bindIp[4];
105+
uint8_t bindIndex;
106+
uint8_t status2;
107+
uint8_t filler[26];
108+
} replay;
109+
110+
memcpy(replay.id,ART_NET_ID, 8);
111+
replay.opCode[0] = ART_POLL_REPLAY;
112+
replay.opCode[1] = ART_POLL_REPLAY >> 8;
113+
114+
memcpy(replay.ipAddress, ether.myip, IP_LEN);
115+
116+
replay.port[0] = 0x36;
117+
replay.port[1] = 0x19;
118+
119+
replay.versInfoH = 0;
120+
replay.versInfoL = 1;
121+
122+
replay.netSwitch = 0;
123+
replay.subSwitch = 0;
124+
125+
replay.oemHi = 0;
126+
replay.oem = 0;
127+
128+
replay.ubeaVersion = 0;
129+
130+
replay.status1 = 0xF0;
131+
132+
replay.estaManLo = 'E';
133+
replay.estaManHi = 'T';
134+
135+
memcpy(replay.shortName,"ArtNetNode 4 ", 18);
136+
memcpy(replay.longName,"ArtNetNode 4 LONG ", 22);
137+
//memcpy(replay.nodeReport,"ArtNetNode 4 LONG ", 64);
138+
139+
replay.numPortsHi = 0;
140+
replay.numPortsLo = 4;
141+
142+
//4x ArtNet Output + DMX512 Mode
143+
replay.portTypes[0] = 1 << 7;
144+
replay.portTypes[1] = 1 << 7;
145+
replay.portTypes[2] = 1 << 7;
146+
replay.portTypes[3] = 1 << 7;
147+
148+
149+
//replay.goodInput[] //TODO: Unused, transmit as zero
150+
151+
//TODO: Relay check transmission status
152+
replay.goodOutput[0] = 1 << 7;
153+
replay.goodOutput[1] = 1 << 7;
154+
replay.goodOutput[2] = 1 << 7;
155+
replay.goodOutput[3] = 1 << 7;
156+
157+
replay.style = 0x00; //Style 0x00 -> A DMX to7from Art-Net device
158+
159+
memcpy(replay.mac, ether.mymac, ETH_LEN);
160+
memcpy(replay.bindIp, ether.myip, IP_LEN);
161+
162+
replay.bindIndex = 1; //Root device
163+
164+
replay.status2 = 1 << 3; //Supports ArtNed 3 + 4 Port adresses
165+
166+
//TODO: Don't use static ip
167+
uint8_t hisip[4] = {0x02, 0x0, 0x0, 123};
168+
169+
//static void sendUdp (char *data,uint8_t len,uint16_t sport, uint8_t *dip, uint16_t dport);
170+
ether.sendUdp((char*)&replay, sizeof(replay), UDP_PORT_ARTNET_REPLY, hisip, UDP_PORT_ARTNET_REPLY ); //*/
27171
}

artnet.h

+20-3
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,34 @@
22
#define _ARTNET_H 1
33

44
#include <avr/io.h>
5+
#include "net.h"
56

67
// Port to listen on
78
#define UDP_PORT_ARTNET 6454 /* (0x1936) */
89
// Port to reply on
910
#define UDP_PORT_ARTNET_REPLY (UDP_PORT_ARTNET + 1)
1011

1112

12-
extern uint8_t getUniverseFPS(uint8_t universe);
1313

14-
extern void universeReceivedTMP(uint8_t universe);
1514

16-
extern void doTimerStuff1Hz(void);
15+
class ArtNet {
16+
17+
public:
18+
static void udpArtNet(uint16_t dest_port, uint8_t src_ip[IP_LEN], uint16_t src_port, const char *data, uint16_t len);
19+
20+
static uint8_t getUniverseFPS(uint8_t universe);
21+
22+
static void universeReceivedTMP(uint8_t universe);
23+
24+
static void doTimerStuff1Hz(void);
25+
26+
private:
27+
static void sendArtPollReplay(void);
28+
};
29+
30+
31+
extern ArtNet artnet;
32+
33+
1734

1835
#endif

dhcp.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
#include <avr/io.h>
1818

19-
#include "ethercard.h"
19+
#include "EtherCard.h"
2020
#include "net.h"
2121
#include "timer.h"
2222

display.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,10 @@ void writeDirect(uint8_t b) {
4848

4949
void pulseEnable(uint8_t _data){
5050
writeDirect(_data | En); // En high
51-
_delay_ms(1); // enable pulse must be >450ns
51+
_delay_us(1); // enable pulse must be >450ns
5252

5353
writeDirect(_data & ~En); // En low
54-
_delay_ms(1); // commands need > 37us to settle
54+
_delay_us(38); // commands need > 37us to settle
5555
}
5656

5757
void write4bits(uint8_t data) {
@@ -71,7 +71,7 @@ void command(uint8_t value) {
7171
send(value, 0);
7272
}
7373

74-
void writeStr(char value[]) {
74+
void writeStr(const char value[]) {
7575
while(*value != 0) {
7676
send(*value++, Rs);
7777
}

display.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858

5959
extern void setupTWI(void);
6060
extern void twiWrite(unsigned char byte);
61-
extern void writeStr(char* value);
61+
extern void writeStr(const char* value);
6262
extern void writeInt(uint8_t value);
6363
extern void writeIntWidth(uint8_t value, uint8_t width);
6464
extern void write(uint8_t value);

dns.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//
55
// 2010-05-20 <jc@wippler.nl>
66

7-
#include "ethercard.h"
7+
#include "EtherCard.h"
88
#include "net.h"
99

1010
#include "timer.h"

enc28j60.cpp

+8-1
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ uint8_t ENC28J60::initialize (uint16_t size, const uint8_t* macaddr) {
408408
while (!readOp(ENC28J60_READ_CTRL_REG, ESTAT) & ESTAT_CLKRDY);
409409

410410

411-
411+
//TODO: Check full/half duplex
412412

413413
writeReg(ERXST, RXSTART_INIT);
414414
writeReg(ERXRDPT, RXSTART_INIT);
@@ -433,6 +433,7 @@ uint8_t ENC28J60::initialize (uint16_t size, const uint8_t* macaddr) {
433433
writeRegByte(MAADR1, macaddr[4]);
434434
writeRegByte(MAADR0, macaddr[5]);
435435
writePhy(PHCON2, PHCON2_HDLDIS);
436+
writePhy(PHCON1, PHCON1_PDPXMD); //Full Duplex mode
436437
SetBank(ECON1);
437438
writeOp(ENC28J60_BIT_FIELD_SET, EIE, EIE_INTIE|EIE_PKTIE);
438439
writeOp(ENC28J60_BIT_FIELD_SET, ECON1, ECON1_RXEN);
@@ -450,6 +451,12 @@ bool ENC28J60::isLinkUp() {
450451
return (readPhyByte(PHSTAT2) >> 2) & 1;
451452
}
452453

454+
bool ENC28J60::isReceiveError () {
455+
bool result = readRegByte(EIR) & EIR_RXERIF;
456+
writeOp(ENC28J60_BIT_FIELD_CLR, EIR, EIR_RXERIF); //Clear flag
457+
return result;
458+
}
459+
453460
/*
454461
struct __attribute__((__packed__)) transmit_status_vector {
455462
uint16_t transmitByteCount;

enc28j60.h

+9-4
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@
2323
// the entire available packet buffer space is allocated
2424

2525
#define RXSTART_INIT 0x0000 // start of RX buffer, (must be zero, Rev. B4 Errata point 5)
26-
#define RXSTOP_INIT 0x1BFF // end of RX buffer, room for 2 packets
26+
#define RXSTOP_INIT 0x15FF // end of RX buffer, room for 2 packets
2727

28-
#define TXSTART_INIT 0x1C00 // start of TX buffer, room for 1 packet
29-
#define TXSTOP_INIT 0x1EFF // end of TX buffer
28+
#define TXSTART_INIT 0x1600 // start of TX buffer, room for 1 packet
29+
#define TXSTOP_INIT 0x1BDC // end of TX buffer
3030

31-
#define SCRATCH_START 0x1F00 // start of scratch area
31+
#define SCRATCH_START 0x1BDD // start of scratch area
3232
#define SCRATCH_LIMIT 0x2000 // past end of area, i.e. 3 Kb
3333
#define SCRATCH_PAGE_SHIFT 6 // addressing is in pages of 64 bytes
3434
#define SCRATCH_PAGE_SIZE (1 << SCRATCH_PAGE_SHIFT)
@@ -67,6 +67,11 @@ class ENC28J60 {
6767
*/
6868
static bool isLinkUp ();
6969

70+
/** @brief Check if an receive error occured and resets the flag
71+
* @return <i>bool</i> True if an receive error occured(Datasheet 12.1.2)
72+
*/
73+
static bool isReceiveError ();
74+
7075
/** @brief Sends data to network interface
7176
* @param len Size of data to send
7277
* @note Data buffer is shared by recieve and transmit functions

images/ArtNetNode_Display.jpeg

63.4 KB
Loading

images/ArtNetNode_Front1.jpeg

125 KB
Loading

images/ArtNetNode_FullHousing.jpeg

116 KB
Loading

images/ArtNetNode_PCB.jpeg

134 KB
Loading

images/ArtNetNode_Prototype_1.jpeg

165 KB
Loading

images/ArtNetNode_Prototype_2.jpeg

154 KB
Loading

0 commit comments

Comments
 (0)