diff --git a/boards/omnibus/f4sd/default.cmake b/boards/omnibus/f4sd/default.cmake
index 9ffd3229658e2d1fb56a1e4bd5ed18ada6279813..77e7922b4fa11bbd8d3c21754b0b250f50853e83 100644
--- a/boards/omnibus/f4sd/default.cmake
+++ b/boards/omnibus/f4sd/default.cmake
@@ -42,6 +42,7 @@ px4_add_board(
 		#telemetry # all available telemetry drivers
 		telemetry/frsky_telemetry
 		#test_ppm
+		osd
 
 	MODULES
 		attitude_estimator_q
diff --git a/boards/omnibus/f4sd/src/board_config.h b/boards/omnibus/f4sd/src/board_config.h
index 9c2000a24a4a0dca21924d349b8e2b2816f8feda..4fc43f6ee3139f41b127f7f3b57ad3dd862fe8bb 100644
--- a/boards/omnibus/f4sd/src/board_config.h
+++ b/boards/omnibus/f4sd/src/board_config.h
@@ -167,6 +167,7 @@
 #define GPIO_SPI3_MOSI_OFF           _PIN_OFF(GPIO_SPI3_MOSI)
 /* SPI 3 CS's  off */
 #define GPIO_SPI3_CS_BARO_OFF        _PIN_OFF(GPIO_SPI3_CS_BARO)
+#define GPIO_SPI3_CS_OSD_OFF        _PIN_OFF(GPIO_SPI3_CS_OSD)
 
 // One device per bus
 #define PX4_SPI_BUS_SENSORS         1
@@ -174,6 +175,7 @@
 #define PX4_SPIDEV_ICM_20602        1
 #define PX4_SPIDEV_BARO_BUS         3
 #define PX4_SPIDEV_BARO             1
+#define PX4_SPIDEV_OSD              2
 
 /* USB OTG FS
  *
@@ -186,6 +188,7 @@
 /*----------------------------------------------------------*/
 
 #define PX4_SPI_BUS_BARO         3
+#define PX4_SPI_BUS_OSD			 3
 
 #define PX4_I2C_BUS_EXPANSION    2
 #define PX4_I2C_BUS_LED          PX4_I2C_BUS_EXPANSION
diff --git a/boards/omnibus/f4sd/src/spi.c b/boards/omnibus/f4sd/src/spi.c
index 16588695b688b7e3adbc02d5539803c1137226eb..a3144dcfd2854e99119199514b36f4b20ccdeeb9 100644
--- a/boards/omnibus/f4sd/src/spi.c
+++ b/boards/omnibus/f4sd/src/spi.c
@@ -76,6 +76,7 @@ __EXPORT void stm32_spiinitialize()
 	stm32_configgpio(GPIO_SPI_CS_MEMS);
 	stm32_configgpio(GPIO_SPI_CS_SDCARD);
 	stm32_configgpio(GPIO_SPI3_CS_BARO);
+	stm32_configgpio(GPIO_SPI3_CS_OSD);
 }
 
 __EXPORT void stm32_spi1select(FAR struct spi_dev_s *dev, uint32_t devid, bool selected)
@@ -107,6 +108,7 @@ __EXPORT void stm32_spi3select(FAR struct spi_dev_s *dev, uint32_t devid, bool s
 	UNUSED(devid);
 	/* SPI select is active low, so write !selected to select the device */
 	px4_arch_gpiowrite(GPIO_SPI3_CS_BARO, !selected);
+	px4_arch_gpiowrite(GPIO_SPI3_CS_OSD, !selected);
 }
 
 __EXPORT uint8_t stm32_spi3status(FAR struct spi_dev_s *dev, uint32_t devid)
@@ -138,6 +140,8 @@ __EXPORT void board_spi_reset(int ms)
 	/* disable SPI bus 3  CS */
 	stm32_configgpio(GPIO_SPI3_CS_BARO_OFF);
 	stm32_gpiowrite(GPIO_SPI3_CS_BARO_OFF, 0);
+	stm32_configgpio(GPIO_SPI3_CS_OSD_OFF);
+	stm32_gpiowrite(GPIO_SPI3_CS_OSD_OFF, 0);
 
 	/* disable SPI bus 1*/
 	stm32_configgpio(GPIO_SPI1_SCK_OFF);
diff --git a/src/drivers/osd/CMakeLists.txt b/src/drivers/osd/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..89dc8a180874f17e331335061fc9a455224e62c7
--- /dev/null
+++ b/src/drivers/osd/CMakeLists.txt
@@ -0,0 +1,39 @@
+############################################################################
+#
+#   Copyright (c) 2018 PX4 Development Team. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in
+#    the documentation and/or other materials provided with the
+#    distribution.
+# 3. Neither the name PX4 nor the names of its contributors may be
+#    used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+############################################################################
+px4_add_module(
+	MODULE drivers__osd
+	MAIN osd
+	SRCS
+		osd.cpp
+	)
+# vim: set noet ft=cmake fenc=utf-8 ff=unix :
\ No newline at end of file
diff --git a/src/drivers/osd/osd.cpp b/src/drivers/osd/osd.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f5fbbbc26b74adaa759168d22a98c4dc16c95024
--- /dev/null
+++ b/src/drivers/osd/osd.cpp
@@ -0,0 +1,672 @@
+/****************************************************************************
+ *
+ *   Copyright (c) 2018 PX4 Development Team. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name PX4 nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/**
+ * @file osd.cpp
+ * @author Daniele Pettenuzzo
+ *
+ * Driver for the ATXXXX chip on the omnibus fcu connected via SPI.
+ */
+
+#include "osd.h"
+
+
+OSD::OSD(int bus) :
+	SPI("OSD", OSD_DEVICE_PATH, bus, OSD_SPIDEV, SPIDEV_MODE0, OSD_SPI_BUS_SPEED),
+	_measure_ticks(0),
+	_sample_perf(perf_alloc(PC_ELAPSED, "osd_read")),
+	_comms_errors(perf_alloc(PC_COUNT, "osd_com_err")),
+	_tx_mode(1),
+	_battery_sub(-1),
+	_local_position_sub(-1),
+	_vehicle_status_sub(-1),
+	_battery_voltage_filtered_v(0),
+	_battery_discharge_mah(0),
+	_battery_valid(false),
+	_local_position_z(0),
+	_local_position_valid(false),
+	_arming_state(1),
+	_arming_timestamp(0)
+{
+	// enable debug() calls
+	_debug_enabled = false;
+
+	// get params
+	_p_tx_mode = param_find("OSD_TX_MODE");
+	param_get(_p_tx_mode, (int32_t *)&_tx_mode);
+
+	// work_cancel in the dtor will explode if we don't do this...
+	memset(&_work, 0, sizeof(_work));
+}
+
+OSD::~OSD()
+{
+	/* make sure we are truly inactive */
+	stop();
+
+	// free perf counters
+	perf_free(_sample_perf);
+	perf_free(_comms_errors);
+}
+
+
+int
+OSD::init()
+{
+	/* do SPI init (and probe) first */
+	if (SPI::init() != PX4_OK) {
+		goto fail;
+	}
+
+	if (reset() != PX4_OK) {
+		goto fail;
+	}
+
+	if (init_osd() != PX4_OK) {
+		goto fail;
+	}
+
+	for (int i = 0; i < OSD_CHARS_PER_ROW; i++) {
+		for (int j = 0; j < 17; j++) {
+			add_character_to_screen(' ', i, j);
+		}
+	}
+
+	_battery_sub = orb_subscribe(ORB_ID(battery_status));
+	// _local_position_sub = orb_subscribe(ORB_ID(vehicle_local_position));
+	_vehicle_status_sub = orb_subscribe(ORB_ID(vehicle_status));
+
+	return PX4_OK;
+
+fail:
+	return PX4_ERROR;
+
+}
+
+
+int
+OSD::probe()
+{
+	uint8_t data = 0;
+	int ret = PX4_OK;
+
+	ret |= writeRegister(0x00, 0x01); //disable video output
+	ret |= readRegister(0x00, &data, 1);
+
+	if (data != 1 || ret != PX4_OK) {
+		printf("probe error\n");
+	}
+
+	return ret;
+}
+
+int
+OSD::init_osd()
+{
+	int ret = PX4_OK;
+	uint8_t data = OSD_ZERO_BYTE;
+
+	if (_tx_mode) {
+		data |= OSD_PAL_TX_MODE;
+	}
+
+	ret |= writeRegister(0x00, data);
+	ret |= writeRegister(0x04, OSD_ZERO_BYTE);
+
+	enable_screen();
+
+	// writeRegister(0x00, 0x48) != PX4_OK) { //DMM set to 0
+	// 	goto fail;
+	// }
+
+	return ret;
+
+}
+
+
+int
+OSD::ioctl(device::file_t *filp, int cmd, unsigned long arg)
+{
+	return -1;
+}
+
+ssize_t
+OSD::read(device::file_t *filp, char *buffer, size_t buflen)
+{
+	return -1;
+}
+
+
+int
+OSD::readRegister(unsigned reg, uint8_t *data, unsigned count)
+{
+	uint8_t cmd[5]; 					// read up to 4 bytes
+	int ret;
+
+	cmd[0] = DIR_READ(reg);
+
+	ret = transfer(&cmd[0], &cmd[0], count + 1);
+
+	if (OK != ret) {
+		perf_count(_comms_errors);
+		DEVICE_LOG("spi::transfer returned %d", ret);
+		return ret;
+	}
+
+	memcpy(&data[0], &cmd[1], count);
+
+	return ret;
+
+}
+
+
+int
+OSD::writeRegister(unsigned reg, uint8_t data)
+{
+	uint8_t cmd[2]; 						// write 1 byte
+	int ret;
+
+	cmd[0] = DIR_WRITE(reg);
+	cmd[1] = data;
+
+	ret = transfer(&cmd[0], nullptr, 2);
+
+	if (OK != ret) {
+		perf_count(_comms_errors);
+		DEVICE_LOG("spi::transfer returned %d", ret);
+		return ret;
+	}
+
+	return ret;
+
+}
+
+int
+OSD::add_character_to_screen(char c, uint8_t pos_x, uint8_t pos_y)
+{
+
+	uint16_t position = (OSD_CHARS_PER_ROW * pos_y) + pos_x;
+	uint8_t position_lsb;
+	int ret = PX4_OK;
+
+	if (position > 0xFF) {
+		position_lsb = static_cast<uint8_t>(position) - 0xFF;
+		ret |= writeRegister(0x05, 0x01); //DMAH
+
+	} else {
+		position_lsb = static_cast<uint8_t>(position);
+		ret |= writeRegister(0x05, 0x00); //DMAH
+	}
+
+	ret |= writeRegister(0x06, position_lsb); //DMAL
+	ret |= writeRegister(0x07, c);
+
+	return ret;
+}
+
+int
+OSD::add_battery_symbol(uint8_t pos_x, uint8_t pos_y)
+{
+	return add_character_to_screen(146, pos_x, pos_y);
+}
+
+int
+OSD::add_battery_info(uint8_t pos_x, uint8_t pos_y)
+{
+	char buf[5];
+	int ret = PX4_OK;
+
+	sprintf(buf, "%4.2f", (double)_battery_voltage_filtered_v);
+
+	for (int i = 0; i < 5; i++) {
+		ret |= add_character_to_screen(buf[i], pos_x + i, pos_y);
+	}
+
+	ret |= add_character_to_screen('V', pos_x + 5, pos_y);
+
+	pos_y++;
+
+	sprintf(buf, "%4d", (int)_battery_discharge_mah);
+
+	for (int i = 0; i < 5; i++) {
+		ret |= add_character_to_screen(buf[i], pos_x + i, pos_y);
+	}
+
+	ret |= add_character_to_screen(7, pos_x + 5, pos_y); // mAh symbol
+
+	return ret;
+}
+
+int
+OSD::add_altitude_symbol(uint8_t pos_x, uint8_t pos_y)
+{
+	return add_character_to_screen(154, pos_x, pos_y);
+}
+
+int
+OSD::add_altitude(uint8_t pos_x, uint8_t pos_y)
+{
+	char buf[5];
+	int ret = PX4_OK;
+
+	sprintf(buf, "%4.2f", (double)_local_position_z);
+
+	for (int i = 0; i < 5; i++) {
+		ret |= add_character_to_screen(buf[i], pos_x + i, pos_y);
+	}
+
+	ret |= add_character_to_screen('m', pos_x + 5, pos_y);
+
+	return ret;
+}
+
+int
+OSD::add_flighttime_symbol(uint8_t pos_x, uint8_t pos_y)
+{
+	return add_character_to_screen(112, pos_x, pos_y);
+}
+
+int
+OSD::add_flighttime(float flight_time, uint8_t pos_x, uint8_t pos_y)
+{
+	char buf[6];
+	int ret = PX4_OK;
+
+	sprintf(buf, "%5.1f", (double)flight_time);
+
+	for (int i = 0; i < 6; i++) {
+		ret |= add_character_to_screen(buf[i], pos_x + i, pos_y);
+	}
+
+	return ret;
+}
+
+int
+OSD::enable_screen()
+{
+	uint8_t data;
+	int ret = PX4_OK;
+
+	ret |= readRegister(0x00, &data, 1);
+	ret |= writeRegister(0x00, data | 0x48);
+
+	return ret;
+}
+
+int
+OSD::disable_screen()
+{
+	uint8_t data;
+	int ret = PX4_OK;
+
+	ret |= readRegister(0x00, &data, 1);
+	ret |= writeRegister(0x00, data & 0xF7);
+
+	return ret;
+}
+
+
+int
+OSD::update_topics()//TODO have an argument to choose what to update and return validity
+{
+	struct battery_status_s battery = {};
+	// struct vehicle_local_position_s local_position = {};
+	struct vehicle_status_s vehicle_status = {};
+
+	bool updated = false;
+
+	/* update battery subscription */
+	orb_check(_battery_sub, &updated);
+
+	if (updated) {
+		orb_copy(ORB_ID(battery_status), _battery_sub, &battery);
+
+		if (battery.connected) {
+			_battery_voltage_filtered_v = battery.voltage_filtered_v;
+			_battery_discharge_mah = battery.discharged_mah;
+			_battery_valid = true;
+
+		} else {
+			_battery_valid = false;
+		}
+	}
+
+	/* update vehicle local position subscription */
+	// orb_check(_local_position_sub, &updated);
+
+	// if (updated) {
+	// 	if (local_position.z_valid) {
+	// 		_local_position_z = -local_position.z;
+	// 		_local_position_valid = true;
+
+	// 	} else {
+	// 		_local_position_valid = false;
+	// 	}
+	// }
+
+	/* update vehicle status subscription */
+	orb_check(_vehicle_status_sub, &updated);
+
+	if (updated) {
+		if (vehicle_status.arming_state == 2 && _arming_state == 1) {
+			_arming_timestamp = hrt_absolute_time();
+			_arming_state = 2;
+
+		} else if (vehicle_status.arming_state == 1 && _arming_state == 2) {
+			_arming_state = 1;
+		}
+
+
+		if (vehicle_status.nav_state == vehicle_status.NAVIGATION_STATE_ACRO) {
+			add_character_to_screen('A', 1, 7);
+			add_character_to_screen('C', 2, 7);
+			add_character_to_screen('R', 3, 7);
+			add_character_to_screen('O', 4, 7);
+
+		} else if (vehicle_status.nav_state == vehicle_status.NAVIGATION_STATE_STAB) {
+			add_character_to_screen('S', 1, 8);
+			add_character_to_screen('T', 2, 8);
+			add_character_to_screen('A', 3, 8);
+			add_character_to_screen('B', 4, 8);
+			add_character_to_screen('I', 5, 8);
+			add_character_to_screen('L', 6, 8);
+			add_character_to_screen('I', 7, 8);
+			add_character_to_screen('Z', 8, 8);
+			add_character_to_screen('E', 9, 8);
+
+		} else if (vehicle_status.nav_state == vehicle_status.NAVIGATION_STATE_MANUAL) {
+			// add_character_to_screen('A', uint8_t pos_x, uint8_t pos_y)
+			// add_character_to_screen('C', uint8_t pos_x, uint8_t pos_y)
+			// add_character_to_screen('R', uint8_t pos_x, uint8_t pos_y)
+			// add_character_to_screen('O', uint8_t pos_x, uint8_t pos_y)
+		}
+
+		// _arming_state = vehicle_status.arming_state;
+	}
+
+	return PX4_OK;
+}
+
+
+int
+OSD::update_screen()
+{
+	int ret = PX4_OK;
+
+	if (_battery_valid) {
+		ret |= add_battery_symbol(1, 1);
+		ret |= add_battery_info(2, 1);
+	}
+
+	if (_local_position_valid) {
+		ret |= add_altitude_symbol(1, 3);
+		ret |= add_altitude(2, 3);
+	}
+
+	// if (_arming_state == 2) {
+	float flight_time_sec = static_cast<float>((hrt_absolute_time() - _arming_timestamp) / (1.0e6));
+	ret |= add_flighttime_symbol(1, 5);
+	ret |= add_flighttime(flight_time_sec, 2, 5);
+	// }
+
+	// enable_screen();
+
+	return ret;
+
+}
+
+
+void
+OSD::start()
+{
+	/* schedule a cycle to start things */
+	work_queue(LPWORK, &_work, (worker_t)&OSD::cycle_trampoline, this, USEC2TICK(OSD_US));
+}
+
+void
+OSD::stop()
+{
+	work_cancel(LPWORK, &_work);
+}
+
+int
+OSD::reset()
+{
+	int ret = writeRegister(0x00, 0x02);
+	usleep(100);
+
+	return ret;
+}
+
+void
+OSD::cycle_trampoline(void *arg)
+{
+	OSD *dev = (OSD *)arg;
+
+	dev->cycle();
+}
+
+void
+OSD::cycle()
+{
+	update_topics();
+
+	if (_battery_valid || _local_position_valid || _arming_state > 1) {
+		update_screen();
+	}
+
+	/* schedule a fresh cycle call when the measurement is done */
+	work_queue(LPWORK,
+		   &_work,
+		   (worker_t)&OSD::cycle_trampoline,
+		   this,
+		   USEC2TICK(OSD_UPDATE_RATE));
+
+}
+
+void
+OSD::print_info()
+{
+	perf_print_counter(_sample_perf);
+	perf_print_counter(_comms_errors);
+	printf("poll interval:  %u ticks\n", _measure_ticks);
+	printf("battery_status: %.3f\n", (double)_battery_voltage_filtered_v);
+	printf("arming_state: %d\n", _arming_state);
+	printf("arming_timestamp: %5.1f\n", (double)_arming_timestamp);
+
+}
+
+
+/**
+ * Local functions in support of the shell command.
+ */
+namespace osd
+{
+
+OSD	*g_dev;
+
+int	start(int spi_bus);
+int	stop();
+int	info();
+void usage();
+
+
+/**
+ * Start the driver.
+ */
+int
+start(int spi_bus)
+{
+	int fd;
+
+	if (g_dev != nullptr) {
+		PX4_ERR("already started");
+		goto fail;
+	}
+
+	/* create the driver */
+	g_dev = new OSD(spi_bus);
+
+	if (g_dev == nullptr) {
+		goto fail;
+	}
+
+	if (OK != g_dev->init()) {
+		goto fail;
+	}
+
+	fd = open(OSD_DEVICE_PATH, O_RDONLY);
+
+	if (fd < 0) {
+		goto fail;
+	}
+
+	g_dev->start();
+
+	return PX4_OK;
+
+fail:
+
+	if (g_dev != nullptr) {
+		delete g_dev;
+		g_dev = nullptr;
+	}
+
+	PX4_ERR("driver start failed");
+	return PX4_ERROR;
+}
+
+/**
+ * Stop the driver
+ */
+int
+stop()
+{
+	if (g_dev != nullptr) {
+		delete g_dev;
+		g_dev = nullptr;
+
+	} else {
+		PX4_ERR("driver not running");
+		return PX4_ERROR;
+	}
+
+	return PX4_OK;
+}
+
+/**
+ * Print a little info about the driver.
+ */
+int
+info()
+{
+	if (g_dev == nullptr) {
+		PX4_ERR("driver not running");
+		return PX4_ERROR;
+	}
+
+	printf("state @ %p\n", g_dev);
+	g_dev->print_info();
+
+	return PX4_OK;
+}
+
+/**
+ * Print a little info about how to start/stop/use the driver
+ */
+void usage()
+{
+	PX4_INFO("usage: osd {start|stop|status'}");
+	PX4_INFO("    [-b SPI_BUS]");
+}
+
+} // namespace osd
+
+
+int
+osd_main(int argc, char *argv[])
+{
+	if (argc < 2) {
+		osd::usage();
+		return PX4_ERROR;
+	}
+
+	// don't exit from getopt loop to leave getopt global variables in consistent state,
+	// set error flag instead
+	bool err_flag = false;
+	int ch;
+	int myoptind = 1;
+	const char *myoptarg = nullptr;
+	int spi_bus = OSD_BUS;
+
+	while ((ch = px4_getopt(argc, argv, "b:", &myoptind, &myoptarg)) != EOF) {
+		switch (ch) {
+		case 'b':
+			spi_bus = (uint8_t)atoi(myoptarg);
+			break;
+
+		default:
+			err_flag = true;
+			break;
+		}
+	}
+
+	if (err_flag) {
+		osd::usage();
+		return PX4_ERROR;
+	}
+
+	/*
+	 * Start/load the driver.
+	 */
+	if (!strcmp(argv[myoptind], "start")) {
+		return osd::start(spi_bus);
+	}
+
+	/*
+	 * Stop the driver
+	 */
+	if (!strcmp(argv[myoptind], "stop")) {
+		return osd::stop();
+	}
+
+	/*
+	 * Print driver information.
+	 */
+	if (!strcmp(argv[myoptind], "info") || !strcmp(argv[myoptind], "status")) {
+		return osd::info();
+	}
+
+	osd::usage();
+	return PX4_ERROR;
+}
diff --git a/src/drivers/osd/osd.h b/src/drivers/osd/osd.h
new file mode 100644
index 0000000000000000000000000000000000000000..ba9c32a854db87e38a2845539e1d755afe7e67f0
--- /dev/null
+++ b/src/drivers/osd/osd.h
@@ -0,0 +1,199 @@
+/****************************************************************************
+ *
+ *   Copyright (c) 2018 PX4 Development Team. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name PX4 nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#pragma once
+
+/**
+ * @file osd.h
+ * @author Daniele Pettenuzzo
+ *
+ * Driver for the ATXXXX chip on the omnibus fcu connected via SPI.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <perf/perf_counter.h>
+#include <parameters/param.h>
+#include <px4_getopt.h>
+#include <px4_workqueue.h>
+
+#include <board_config.h>
+#include <drivers/drv_hrt.h>
+#include <drivers/device/spi.h>
+
+#include <uORB/uORB.h>
+#include <uORB/topics/battery_status.h>
+#include <uORB/topics/vehicle_local_position.h>
+#include <uORB/topics/vehicle_status.h>
+
+/* Configuration Constants */
+#ifdef PX4_SPI_BUS_OSD
+#define OSD_BUS PX4_SPI_BUS_OSD
+#else
+#error "add the required spi bus from board_config.h here"
+#endif
+
+#ifdef PX4_SPIDEV_OSD
+#define OSD_SPIDEV PX4_SPIDEV_OSD
+#else
+#error "add the required spi bus from board_config.h here"
+#endif
+
+#define OSD_SPI_BUS_SPEED (2000000L) /*  2 MHz  */
+
+#define DIR_READ(a) ((a) | (1 << 7))
+#define DIR_WRITE(a) ((a) & 0x7f)
+
+#define OSD_DEVICE_PATH "/dev/osd"
+
+#define OSD_US 1000 /*  1 ms  */
+#define OSD_UPDATE_RATE 500000 /*  2 Hz  */
+#define OSD_CHARS_PER_ROW	30
+#define OSD_ZERO_BYTE 0x00
+#define OSD_PAL_TX_MODE 0x40
+
+/* OSD Registers addresses */
+
+
+#ifndef CONFIG_SCHED_WORKQUEUE
+# error This requires CONFIG_SCHED_WORKQUEUE.
+#endif
+
+class OSD : public device::SPI
+{
+public:
+	OSD(int bus = OSD_BUS);
+
+	virtual ~OSD();
+
+	virtual int init();
+
+	virtual ssize_t read(device::file_t *filp, char *buffer, size_t buflen);
+
+	virtual int ioctl(device::file_t *filp, int cmd, unsigned long arg);
+
+	/**
+	* Diagnostics - print some basic information about the driver.
+	*/
+	void print_info();
+
+	/**
+	* Initialise the automatic measurement state machine and start it.
+	*
+	* @note This function is called at open and error time.  It might make sense
+	*       to make it more aggressive about resetting the bus in case of errors.
+	*/
+	void start();
+
+protected:
+	virtual int probe();
+
+private:
+	work_s _work;
+
+	int _measure_ticks;
+
+	perf_counter_t _sample_perf;
+	perf_counter_t _comms_errors;
+
+	param_t _p_tx_mode;
+	int32_t _tx_mode;
+
+	int _battery_sub;
+	int _local_position_sub;
+	int _vehicle_status_sub;
+
+	bool _on;
+
+	// battery
+	float _battery_voltage_filtered_v;
+	float _battery_discharge_mah;
+	bool _battery_valid;
+
+	// altitude
+	float _local_position_z;
+	bool _local_position_valid;
+
+	// flight time
+	uint8_t _arming_state;
+	uint64_t _arming_timestamp;
+
+	/**
+	* Stop the automatic measurement state machine.
+	*/
+	void stop();
+
+	/**
+	* Perform a poll cycle; collect from the previous measurement
+	* and start a new one.
+	*/
+	void cycle();
+
+	int reset();
+
+	int init_osd();
+
+	int readRegister(unsigned reg, uint8_t *data, unsigned count);
+	int writeRegister(unsigned reg, uint8_t data);
+
+	int add_character_to_screen(char c, uint8_t pos_x, uint8_t pos_y);
+	int add_battery_symbol(uint8_t pos_x, uint8_t pos_y);
+	int add_battery_info(uint8_t pos_x, uint8_t pos_y);
+	int add_altitude_symbol(uint8_t pos_x, uint8_t pos_y);
+	int add_altitude(uint8_t pos_x, uint8_t pos_y);
+	int add_flighttime_symbol(uint8_t pos_x, uint8_t pos_y);
+	int add_flighttime(float flight_time, uint8_t pos_x, uint8_t pos_y);
+
+	int enable_screen();
+	int disable_screen();
+
+	int update_topics();
+	int	update_screen();
+
+	/**
+	* Static trampoline from the workq context; because we don't have a
+	* generic workq wrapper yet.
+	*
+	* @param arg		Instance pointer for the driver that is polling.
+	*/
+	static void cycle_trampoline(void *arg);
+
+
+};
+/*
+ * Driver 'main' command.
+ */
+extern "C" __EXPORT int osd_main(int argc, char *argv[]);
diff --git a/src/drivers/osd/osd_params.c b/src/drivers/osd/osd_params.c
new file mode 100644
index 0000000000000000000000000000000000000000..5b6802cfd40f4486b8a1c58e42d1cd1c204092d5
--- /dev/null
+++ b/src/drivers/osd/osd_params.c
@@ -0,0 +1,45 @@
+/****************************************************************************
+ *
+ *   Copyright (c) 2018 PX4 Development Team. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name PX4 nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/**
+* ATXXX OSD Chip
+*
+* Select Transmission Standard
+*
+* @value 0 NTSC
+* @value 1 PAL
+*
+* @reboot_required true
+*
+*/
+PARAM_DEFINE_INT32(OSD_TX_MODE, 0);