Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] add HDMI2ETH support #263

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions firmware/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ OBJECTS=\
uptime.o \
version.o \
pcie.o \
eth_stream.o \
$(FIRMBUILD_DIRECTORY)/version_data.o \
$(FIRMBUILD_DIRECTORY)/hdmi_in1.o \
boot-helper-$(CPU).o
Expand Down
17 changes: 17 additions & 0 deletions firmware/ci.c
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,10 @@ static void video_matrix_list(void)
#ifdef CSR_PCIE_PHY_BASE
wprintf("pcie (x):\n");
wprintf(" PCIe buffer\n");
#endif
#ifdef ETHMAC_BASE
wprintf("net (n):\n");
wprintf(" Ethernet stream\n");
#endif
wprintf("pattern (p):\n");
wprintf(" Video pattern\n");
Expand Down Expand Up @@ -703,6 +707,13 @@ static void video_matrix_connect(int source, int sink)
wprintf("Connecting %s to PCIe\n", processor_get_source_name(source));
processor_update();
}
#endif
#ifdef ETHMAC_BASE
else if(sink == VIDEO_OUT_ETH) {
wprintf("Connecting %s to Ethernet\n", processor_get_source_name(source));
processor_set_eth_source(source);
processor_update();
}
#endif
}
}
Expand Down Expand Up @@ -1110,6 +1121,9 @@ void ci_service(void)
else if((strcmp(token, "pcie") == 0) || (strcmp(token, "x") == 0)){
source = VIDEO_IN_PCIE;
}
else if((strcmp(token, "net") == 0) || (strcmp(token, "n") == 0)){
source = VIDEO_IN_ETH;
}
else {
wprintf("Unknown video source: '%s'\n", token);
}
Expand All @@ -1129,6 +1143,9 @@ void ci_service(void)
else if((strcmp(token, "pcie") == 0) || (strcmp(token, "x") == 0)) {
sink = VIDEO_OUT_PCIE;
}
else if((strcmp(token, "net") == 0) || (strcmp(token, "n") == 0)) {
sink = VIDEO_OUT_ETH;
}
else
wprintf("Unknown video sink: '%s'\n", token);

Expand Down
142 changes: 142 additions & 0 deletions firmware/eth_stream.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
#include <stdio.h>
#include <stdarg.h>

#include "eth_stream.h"
#include "ethernet.h"
#include "framebuffer.h"
#include "processor.h"

static struct tcp_socket eth_stream_socket_in;
static struct tcp_socket eth_stream_socket_out;

static int eth_stream_in_pos;
static int eth_stream_out_pos;
static int eth_stream_out_state;

int eth_stream_in_fb_index;

static unsigned int eth_stream_out_next_fb;
static unsigned int eth_stream_out_size;

#ifdef ETHMAC_BASE
static uint8_t eth_stream_in_rx_buffer[ETH_STREAM_DATA_BUFFER_SIZE];
static uint8_t eth_stream_in_tx_buffer[ETH_STREAM_CTL_BUFFER_SIZE];

static uint8_t eth_stream_out_rx_buffer[ETH_STREAM_CTL_BUFFER_SIZE];
static uint8_t eth_stream_out_tx_buffer[ETH_STREAM_DATA_BUFFER_SIZE];
#endif


void eth_stream_init(void)
{
#ifdef ETHMAC_BASE
tcp_socket_register(&eth_stream_socket_in, NULL,
eth_stream_in_rx_buffer, sizeof(eth_stream_in_rx_buffer),
eth_stream_in_tx_buffer, sizeof(eth_stream_in_tx_buffer),
(tcp_socket_data_callback_t) eth_stream_in_data_cb,
(tcp_socket_event_callback_t) eth_stream_in_event_cb);
tcp_socket_listen(&eth_stream_socket_in, ETH_STREAM_PORT_IN);

tcp_socket_register(&eth_stream_socket_out, NULL,
eth_stream_out_rx_buffer, sizeof(eth_stream_out_rx_buffer),
eth_stream_out_tx_buffer, sizeof(eth_stream_out_tx_buffer),
(tcp_socket_data_callback_t) eth_stream_out_data_cb,
(tcp_socket_event_callback_t) eth_stream_out_event_cb);
tcp_socket_listen(&eth_stream_socket_out, ETH_STREAM_PORT_OUT);

eth_stream_in_fb_index = 0;

printf("Ethernet streamer listening on ports %d(in) %d(out)\n", ETH_STREAM_PORT_IN, ETH_STREAM_PORT_OUT);
#endif
}

int eth_stream_in_event_cb(struct tcp_socket *s, void *ptr, tcp_socket_event_t event)
{
switch(event)
{
case TCP_SOCKET_CONNECTED:
eth_stream_in_pos = 0;
break;
case TCP_SOCKET_CLOSED:
eth_stream_in_fb_index = (eth_stream_in_fb_index + 1) % 4;
break;
case TCP_SOCKET_TIMEDOUT:
case TCP_SOCKET_ABORTED:
default:
break;
}
return 0;
}

int eth_stream_in_data_cb(struct tcp_socket *s, void *ptr, const char *rxbuf, int rxlen)
{
char idx = (eth_stream_in_fb_index + 1) % 4;
uint8_t *fb_base = (uint8_t*)fb_ptrdiff_to_main_ram(eth_stream_in_framebuffer_base(idx));
memcpy(fb_base + eth_stream_in_pos, rxbuf, rxlen);
eth_stream_in_pos += rxlen;
return 0;
}

unsigned int eth_stream_in_framebuffer_base(char n) {
return FRAMEBUFFER_BASE_ETH_IN + n * FRAMEBUFFER_SIZE;
}

int eth_stream_out_event_cb(struct tcp_socket *s, void *ptr, tcp_socket_event_t event)
{
switch(event)
{
case TCP_SOCKET_CONNECTED:
eth_stream_out_state = ETH_STREAM_OUT_STATE_READY;
break;
case TCP_SOCKET_DATA_SENT:
break;
case TCP_SOCKET_CLOSED:
case TCP_SOCKET_TIMEDOUT:
case TCP_SOCKET_ABORTED:
default:
eth_stream_out_state = ETH_STREAM_OUT_STATE_OFF;
break;
}
return 0;
}

int eth_stream_out_data_cb(struct tcp_socket *s, void *ptr, const char *rxbuf, int rxlen)
{
return 0;
}

void eth_stream_out_service(void)
{
uint8_t *eth_fb = (uint8_t*)fb_ptrdiff_to_main_ram(FRAMEBUFFER_BASE_ETH_OUT);
uint8_t *src_fb = (uint8_t*)fb_ptrdiff_to_main_ram(eth_stream_out_next_fb);
int xfer_size = min(ETH_STREAM_DATA_BUFFER_SIZE, eth_stream_out_size - eth_stream_out_pos);

switch(eth_stream_out_state)
{
case ETH_STREAM_OUT_STATE_OFF:
return;
case ETH_STREAM_OUT_STATE_READY:
eth_stream_out_size = processor_h_active * processor_v_active * 2;
eth_stream_out_pos = 0;
memcpy(eth_fb, src_fb, eth_stream_out_size);
eth_stream_out_state = ETH_STREAM_OUT_STATE_BUSY;
tcp_socket_send(&eth_stream_socket_out, (uint8_t*)&eth_stream_out_size, 4);
break;
case ETH_STREAM_OUT_STATE_BUSY:
xfer_size = tcp_socket_send(&eth_stream_socket_out, eth_fb + eth_stream_out_pos, xfer_size);
eth_stream_out_pos += xfer_size;
if (eth_stream_out_pos == eth_stream_out_size)
eth_stream_out_state = ETH_STREAM_OUT_STATE_CLOSE;
break;
case ETH_STREAM_OUT_STATE_CLOSE:
tcp_socket_close(&eth_stream_socket_out);
default:
eth_stream_out_state = ETH_STREAM_OUT_STATE_OFF;
break;
}
}

void eth_stream_out_base_write(unsigned int value)
{
eth_stream_out_next_fb = value;
}
40 changes: 40 additions & 0 deletions firmware/eth_stream.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#ifndef __ETH_STREAM_H
#define __ETH_STREAM_H

#include <stdarg.h>

#include "contiki.h"
#include "contiki-net.h"

#define ETH_STREAM_PORT_IN 6000
#define ETH_STREAM_PORT_OUT 6001

#define ETH_STREAM_DATA_BUFFER_SIZE 4096
#define ETH_STREAM_CTL_BUFFER_SIZE 64

#define max(a,b) ((a>b)?a:b)
#define min(a,b) ((a<b)?a:b)

enum {
ETH_STREAM_OUT_STATE_OFF,
ETH_STREAM_OUT_STATE_READY,
ETH_STREAM_OUT_STATE_BUSY,
ETH_STREAM_OUT_STATE_CLOSE,
};

extern int eth_stream_in_fb_index;

void eth_stream_init(void);

int eth_stream_in_event_cb(struct tcp_socket *s, void *ptr, tcp_socket_event_t event);
int eth_stream_in_data_cb(struct tcp_socket *s, void *ptr, const char *rxbuf, int rxlen);

int eth_stream_out_event_cb(struct tcp_socket *s, void *ptr, tcp_socket_event_t event);
int eth_stream_out_data_cb(struct tcp_socket *s, void *ptr, const char *rxbuf, int rxlen);

unsigned int eth_stream_in_framebuffer_base(char n);

void eth_stream_out_service(void);
void eth_stream_out_base_write(unsigned int value);

#endif
23 changes: 14 additions & 9 deletions firmware/framebuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,19 @@
* Frame buffers must be aligned to XXX boundary.
*
* 0x01000000 - Pattern Buffer - Frame Buffer n
* 0x02000000 - PCIe Buffer - Frame Buffer n
* 0x02000000 - Ethernet In Buffer - Frame Buffer n
* 0x03000000 - Ethernet Out Buffer - Frame Buffer n
* 0x04000000 - PCIe Buffer - Frame Buffer n
*
* Each input then has 3 frame buffers spaced like this;
* // HDMI Input 0
* 0x03000000 - HDMI Input 0 - Frame Buffer n
* 0x03040000 - HDMI Input 0 - Frame Buffer n+1
* 0x03080000 - HDMI Input 0 - Frame Buffer n+2
* 0x05000000 - HDMI Input 0 - Frame Buffer n
* 0x05040000 - HDMI Input 0 - Frame Buffer n+1
* 0x05080000 - HDMI Input 0 - Frame Buffer n+2
* // HDMI Input 1
* 0x04000000 - HDMI Input 1 - Frame Buffer n
* 0x04040000 - HDMI Input 1 - Frame Buffer n+1
* 0x04080000 - HDMI Input 1 - Frame Buffer n+2
* 0x06000000 - HDMI Input 1 - Frame Buffer n
* 0x06040000 - HDMI Input 1 - Frame Buffer n+1
* 0x06080000 - HDMI Input 1 - Frame Buffer n+2
* ...
* // HDMI Input x
* 0x0.000000 - HDMI Input x - Frame Buffer n
Expand All @@ -42,6 +44,7 @@
*/
#define FRAMEBUFFER_OFFSET 0x01000000
#define FRAMEBUFFER_PATTERNS 1
#define FRAMEBUFFER_ETH_BUFFERS 2
#define FRAMEBUFFER_PCIE_BUFFERS 1

#define FRAMEBUFFER_PIXELS_X 1920 // pixels
Expand All @@ -50,8 +53,10 @@

#define FRAMEBUFFER_BASE(x) ((x+1)*FRAMEBUFFER_OFFSET)
#define FRAMEBUFFER_BASE_PATTERN FRAMEBUFFER_BASE(0)
#define FRAMEBUFFER_BASE_PCIE FRAMEBUFFER_BASE(FRAMEBUFFER_PATTERNS)
#define FRAMEBUFFER_BASE_HDMI_INPUT(x) FRAMEBUFFER_BASE(x+FRAMEBUFFER_PATTERNS+FRAMEBUFFER_PCIE_BUFFERS)
#define FRAMEBUFFER_BASE_ETH_IN FRAMEBUFFER_BASE(FRAMEBUFFER_PATTERNS)
#define FRAMEBUFFER_BASE_ETH_OUT FRAMEBUFFER_BASE(FRAMEBUFFER_PATTERNS+1)
#define FRAMEBUFFER_BASE_PCIE FRAMEBUFFER_BASE(FRAMEBUFFER_PATTERNS+FRAMEBUFFER_ETH_BUFFERS)
#define FRAMEBUFFER_BASE_HDMI_INPUT(x) FRAMEBUFFER_BASE(x+FRAMEBUFFER_PATTERNS+FRAMEBUFFER_ETH_BUFFERS+FRAMEBUFFER_PCIE_BUFFERS)


// Largest frame size at 16bpp (ish)
Expand Down
2 changes: 2 additions & 0 deletions firmware/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "processor.h"
#include "stdio_wrap.h"
#include "telnet.h"
#include "eth_stream.h"
#include "tofe_eeprom.h"
#include "uptime.h"
#include "version.h"
Expand Down Expand Up @@ -98,6 +99,7 @@ int main(void)
ethernet_init(mac_addr, ip_addr);
etherbone_init();
telnet_init();
eth_stream_init();
#endif

// Reboot the FX2 chip into HDMI2USB mode
Expand Down
25 changes: 24 additions & 1 deletion firmware/processor.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "processor.h"
#include "heartbeat.h"
#include "pcie.h"
#include "eth_stream.h"

/*
----------------->>> Time ----------->>>
Expand Down Expand Up @@ -704,12 +705,18 @@ void processor_set_encoder_source(int source) {
processor_encoder_source = source;
}

void processor_set_eth_source(int source) {
processor_eth_source = source;
}

char * processor_get_source_name(int source) {
memset(processor_buffer, 0, 16);
if(source == VIDEO_IN_PATTERN)
sprintf(processor_buffer, "pattern");
else if(source == VIDEO_IN_PCIE)
sprintf(processor_buffer, "pcie");
else if(source == VIDEO_IN_ETH)
sprintf(processor_buffer, "eth");
else
sprintf(processor_buffer, "input%d", source);
return processor_buffer;
Expand Down Expand Up @@ -737,6 +744,8 @@ void processor_update(void)
if(processor_hdmi_out0_source == VIDEO_IN_PATTERN)
hdmi_out0_core_initiator_base_write(pattern_framebuffer_base());

if(processor_hdmi_out0_source == VIDEO_IN_ETH)
hdmi_out0_core_initiator_base_write(eth_stream_in_framebuffer_base(eth_stream_in_fb_index));
#endif

#ifdef CSR_HDMI_OUT1_BASE
Expand Down Expand Up @@ -779,6 +788,18 @@ void processor_update(void)
/* FIXME: add code here when PCIe output starts to use DMA */
#endif

#ifdef ETHMAC_BASE
/* ethernet stream */
#ifdef CSR_HDMI_IN0_BASE
if(processor_eth_source == VIDEO_IN_HDMI_IN0) {
eth_stream_out_base_write(hdmi_in0_framebuffer_base(hdmi_in0_fb_index));
}
#endif

if(processor_eth_source == VIDEO_IN_PATTERN)
eth_stream_out_base_write(pattern_framebuffer_base());
#endif

#ifdef CSR_HDMI_IN0_BASE
hb_service(hdmi_in0_framebuffer_base(hdmi_in0_fb_index));
#endif
Expand All @@ -801,7 +822,9 @@ void processor_service(void)
#ifdef ENCODER_BASE
encoder_service();
#endif

#ifdef ETHMAC_BASE
eth_stream_out_service();
#endif
}

struct video_timing* processor_get_custom_mode(void)
Expand Down
Loading