mirror of
				https://github.com/hyperion-project/hyperion.ng.git
				synced 2025-03-01 10:33:28 +00:00 
			
		
		
		
	Implemented the Ldp6803 device.
Former-commit-id: e38f7d697fbf137d89bfefb1503848a771f51dad
This commit is contained in:
		| @@ -10,8 +10,9 @@ | |||||||
| #include <hyperion/LedDevice.h> | #include <hyperion/LedDevice.h> | ||||||
| #include <hyperion/ImageProcessorFactory.h> | #include <hyperion/ImageProcessorFactory.h> | ||||||
|  |  | ||||||
| #include "LedDeviceWs2801.h" | #include "LedDeviceLdp6803.h" | ||||||
| #include "LedDeviceTest.h" | #include "LedDeviceTest.h" | ||||||
|  | #include "LedDeviceWs2801.h" | ||||||
|  |  | ||||||
| #include "LinearColorSmoothing.h" | #include "LinearColorSmoothing.h" | ||||||
|  |  | ||||||
| @@ -36,9 +37,20 @@ LedDevice* Hyperion::createDevice(const Json::Value& deviceConfig) | |||||||
|  |  | ||||||
| 		device = deviceWs2801; | 		device = deviceWs2801; | ||||||
| 	} | 	} | ||||||
|  | 	else if (type == "ldp6803") | ||||||
|  | 	{ | ||||||
|  | 		const std::string output = deviceConfig["output"].asString(); | ||||||
|  | 		const unsigned rate      = deviceConfig["rate"].asInt(); | ||||||
|  |  | ||||||
|  | 		LedDeviceLdp6803* deviceLdp6803 = new LedDeviceLdp6803(output, rate); | ||||||
|  | 		deviceLdp6803->open(); | ||||||
|  |  | ||||||
|  | 		device = deviceLdp6803; | ||||||
|  | 	} | ||||||
| 	else if (type == "test") | 	else if (type == "test") | ||||||
| 	{ | 	{ | ||||||
| 		device = new LedDeviceTest(); | 		const std::string output = deviceConfig["output"].asString(); | ||||||
|  | 		device = new LedDeviceTest(output); | ||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
|   | |||||||
| @@ -10,80 +10,48 @@ | |||||||
| // hyperion local includes | // hyperion local includes | ||||||
| #include "LedDeviceLdp6803.h" | #include "LedDeviceLdp6803.h" | ||||||
|  |  | ||||||
| LedDeviceLDP6803::LedDeviceLDP6803(const std::string& outputDevice, const unsigned baudrate) : | LedDeviceLdp6803::LedDeviceLdp6803(const std::string& outputDevice, const unsigned baudrate) : | ||||||
| 	LedSpiDevice(outputDevice, baudrate), | 	LedSpiDevice(outputDevice, baudrate), | ||||||
| 	mLedCount(0) | 	_ledBuffer(0) | ||||||
| { | { | ||||||
| 	latchTime.tv_sec = 0; | 	// empty | ||||||
| 	latchTime.tv_nsec = 500000; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| int LedDeviceLDP6803::write(const std::vector<RgbColor> &ledValues) | int LedDeviceLdp6803::write(const std::vector<RgbColor> &ledValues) | ||||||
| { | { | ||||||
| 	mLedCount = ledValues.size(); | 	// Reconfigure if the current connfiguration does not match the required configuration | ||||||
|  | 	if (ledValues.size() != _ledBuffer.size()) | ||||||
| 	// Define buffer sizes based on number of leds |  | ||||||
| 	// buffsize for actual buffer to be sent via SPI pins |  | ||||||
| 	// tempbuffsize for RGB data processing. |  | ||||||
| 	// buffsize = 4 zero bytes + 2 bytes per LED |  | ||||||
| 	// tempbuffsize will hold RGB values, so 3 bytes per LED |  | ||||||
|  |  | ||||||
| 	int buffsize = (mLedCount * 2) + 4; |  | ||||||
| 	int tempbuffsize = mLedCount *3; |  | ||||||
| 	int i,r,g,b,d,count; |  | ||||||
|  |  | ||||||
| 	uint8_t m_buff[buffsize]; |  | ||||||
| 	const uint8_t *temp_buff;//[tempbuffsize]; |  | ||||||
|  |  | ||||||
| 	if (mFid < 0) |  | ||||||
| 	{ | 	{ | ||||||
| 			std::cerr << "Can not write to device which is open." << std::endl; | 		// Initialise the buffer with all 'black' values | ||||||
| 			return -1; | 		_ledBuffer.resize(ledValues.size() + 2, 0x80); | ||||||
|  | 		_ledBuffer[0] = 0; | ||||||
|  | 		_ledBuffer[1] = 0; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	temp_buff = reinterpret_cast<const uint8_t*>(ledValues.data()); | 	// Copy the colors from the RgbColor vector to the Ldp6803Rgb vector | ||||||
|  | 	for (unsigned iLed=0; iLed<ledValues.size(); ++iLed) | ||||||
| 	// set first 4 bytes to zero |  | ||||||
| 	m_buff[0]=0; |  | ||||||
| 	m_buff[1]=0; |  | ||||||
| 	m_buff[2]=0; |  | ||||||
| 	m_buff[3]=0; |  | ||||||
|  |  | ||||||
| 	// Set counter |  | ||||||
| 	count=4; |  | ||||||
|  |  | ||||||
| 	// Now process RGB values: 0-255 to be |  | ||||||
| 	// converted to 0-31, with bits combined |  | ||||||
| 	// to match hardware protocol |  | ||||||
|  |  | ||||||
| 	for (i=0 ; i < tempbuffsize ; i+=3) { |  | ||||||
| 		r = temp_buff[i] >> 3; |  | ||||||
| 		g = temp_buff[i+1] >> 3; |  | ||||||
| 		b = temp_buff[i+2] >> 3; |  | ||||||
|  |  | ||||||
| 		d = (r * 1024) + (g * 32) + b + 32768; |  | ||||||
|  |  | ||||||
| 		m_buff[count] = d >> 8; |  | ||||||
| 		m_buff[count+1] = d & 0x00FF; |  | ||||||
|  |  | ||||||
| 		count += 2; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	spi.tx_buf = __u64(m_buff); |  | ||||||
| 	spi.len    = buffsize; |  | ||||||
|  |  | ||||||
| 	int retVal = ioctl(mFid, SPI_IOC_MESSAGE(1), &spi); |  | ||||||
|  |  | ||||||
| 	if (retVal == 0) |  | ||||||
| 	{ | 	{ | ||||||
| 		// Sleep to latch the leds (only if write succesfull) | 		const RgbColor& rgb = ledValues[iLed]; | ||||||
| 		nanosleep(&latchTime, NULL); |  | ||||||
|  | 		const char packedRed   = rgb.red   & 0xf8; | ||||||
|  | 		const char packedGreen = rgb.green & 0xf8; | ||||||
|  | 		const char packedBlue  = rgb.blue  & 0xf8; | ||||||
|  | 		const unsigned short packedRgb = 0x80 | (packedRed << 7) | (packedGreen << 2) | (packedBlue >> 3); | ||||||
|  |  | ||||||
|  | 		_ledBuffer[iLed + 2] = packedRgb; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return retVal; | 	// Write the data | ||||||
|  | 	const unsigned bufCnt = _ledBuffer.size() * sizeof(short); | ||||||
|  | 	const char * bufPtr   = reinterpret_cast<const char *>(_ledBuffer.data()); | ||||||
|  | 	if (latch(bufCnt, bufPtr, 0) < 0) | ||||||
|  | 	{ | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| int LedDeviceLDP6803::switchOff() | int LedDeviceLdp6803::switchOff() | ||||||
| { | { | ||||||
| 	return write(std::vector<RgbColor>(mLedCount, RgbColor::BLACK)); | 	return write(std::vector<RgbColor>(_ledBuffer.size(), RgbColor::BLACK)); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -6,7 +6,15 @@ | |||||||
| /// | /// | ||||||
| /// Implementation of the LedDevice interface for writing to LDP6803 led device. | /// Implementation of the LedDevice interface for writing to LDP6803 led device. | ||||||
| /// | /// | ||||||
| class LedDeviceLDP6803 : public LedSpiDevice | /// 00000000 00000000 00000000 00000000 1XXXXXYY YYYZZZZZ 1XXXXXYY YYYZZZZZ ... | ||||||
|  | /// |---------------------------------| |---------------| |---------------| | ||||||
|  | /// 32 zeros to start the frame Led1 Led2 ... | ||||||
|  | /// | ||||||
|  | /// For each led, the first bit is always 1, and then you have 5 bits each for red, green and blue | ||||||
|  | /// (X, Y and Z in the above illustration) making 16 bits per led. Total bits = 32 + (16 x number of | ||||||
|  | /// leds) | ||||||
|  | /// | ||||||
|  | class LedDeviceLdp6803 : public LedSpiDevice | ||||||
| { | { | ||||||
| public: | public: | ||||||
| 	/// | 	/// | ||||||
| @@ -15,7 +23,7 @@ public: | |||||||
| 	/// @param[in] outputDevice The name of the output device (eg '/etc/SpiDev.0.0') | 	/// @param[in] outputDevice The name of the output device (eg '/etc/SpiDev.0.0') | ||||||
| 	/// @param[in] baudrate The used baudrate for writing to the output device | 	/// @param[in] baudrate The used baudrate for writing to the output device | ||||||
| 	/// | 	/// | ||||||
| 	LedDeviceLDP6803(const std::string& outputDevice, const unsigned baudrate); | 	LedDeviceLdp6803(const std::string& outputDevice, const unsigned baudrate); | ||||||
|  |  | ||||||
| 	/// | 	/// | ||||||
| 	/// Writes the led color values to the led-device | 	/// Writes the led color values to the led-device | ||||||
| @@ -29,9 +37,5 @@ public: | |||||||
| 	virtual int switchOff(); | 	virtual int switchOff(); | ||||||
|  |  | ||||||
| private: | private: | ||||||
| 	/// The 'latch' time for latching the shifted-value into the leds | 	std::vector<unsigned short> _ledBuffer; | ||||||
| 	timespec latchTime; |  | ||||||
|  |  | ||||||
| 	/// the number of leds (needed when switching off) |  | ||||||
| 	size_t mLedCount; |  | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -2,8 +2,8 @@ | |||||||
| // Local-Hyperion includes | // Local-Hyperion includes | ||||||
| #include "LedDeviceTest.h" | #include "LedDeviceTest.h" | ||||||
|  |  | ||||||
| LedDeviceTest::LedDeviceTest() : | LedDeviceTest::LedDeviceTest(const std::string& output) : | ||||||
| 	_ofs("/home/pi/LedDevice.out") | 	_ofs(output.empty()?"/home/pi/LedDevice.out":output.c_str()) | ||||||
| { | { | ||||||
| 	// empty | 	// empty | ||||||
| } | } | ||||||
|   | |||||||
| @@ -16,7 +16,7 @@ public: | |||||||
| 	/// | 	/// | ||||||
| 	/// Constructs the test-device, which opens an output stream to the file | 	/// Constructs the test-device, which opens an output stream to the file | ||||||
| 	/// | 	/// | ||||||
| 	LedDeviceTest(); | 	LedDeviceTest(const std::string& output); | ||||||
|  |  | ||||||
| 	/// | 	/// | ||||||
| 	/// Destructor of this test-device | 	/// Destructor of this test-device | ||||||
|   | |||||||
| @@ -15,31 +15,17 @@ LedDeviceWs2801::LedDeviceWs2801(const std::string& outputDevice, const unsigned | |||||||
| 	LedSpiDevice(outputDevice, baudrate), | 	LedSpiDevice(outputDevice, baudrate), | ||||||
| 	mLedCount(0) | 	mLedCount(0) | ||||||
| { | { | ||||||
| 	latchTime.tv_sec  = 0; | 	// empty | ||||||
| 	latchTime.tv_nsec = 500000; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| int LedDeviceWs2801::write(const std::vector<RgbColor> &ledValues) | int LedDeviceWs2801::write(const std::vector<RgbColor> &ledValues) | ||||||
| { | { | ||||||
| 	mLedCount = ledValues.size(); | 	mLedCount = ledValues.size(); | ||||||
|  |  | ||||||
| 	if (mFid < 0) | 	const unsigned dataLen = ledValues.size() * sizeof(RgbColor); | ||||||
| 	{ | 	const char * dataPtr   = reinterpret_cast<const char *>(ledValues.data()); | ||||||
| 		std::cerr << "Can not write to device which is open." << std::endl; |  | ||||||
| 		return -1; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	spi.tx_buf = (__u64)ledValues.data(); |  | ||||||
| 	spi.len    = ledValues.size() * sizeof(RgbColor); |  | ||||||
|  |  | ||||||
| 	int retVal = ioctl(mFid, SPI_IOC_MESSAGE(1), &spi); |  | ||||||
|  |  | ||||||
| 	if (retVal == 0) |  | ||||||
| 	{ |  | ||||||
| 		// Sleep to latch the leds (only if write succesfull) |  | ||||||
| 		nanosleep(&latchTime, NULL); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
|  | 	const int retVal = latch(dataLen, dataPtr, 500000); | ||||||
| 	return retVal; | 	return retVal; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -33,8 +33,6 @@ public: | |||||||
| 	virtual int switchOff(); | 	virtual int switchOff(); | ||||||
|  |  | ||||||
| private: | private: | ||||||
| 	/// The 'latch' time for latching the shifted-value into the leds |  | ||||||
| 	timespec latchTime; |  | ||||||
|  |  | ||||||
| 	/// the number of leds (needed when switching off) | 	/// the number of leds (needed when switching off) | ||||||
| 	size_t mLedCount; | 	size_t mLedCount; | ||||||
|   | |||||||
| @@ -55,3 +55,31 @@ int LedSpiDevice::open() | |||||||
|  |  | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | int LedSpiDevice::latch(const unsigned len, const char * vec, const int latchTime_ns) | ||||||
|  | { | ||||||
|  |  | ||||||
|  | 	if (mFid < 0) | ||||||
|  | 	{ | ||||||
|  | 		return -1; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	spi.tx_buf = __u64(vec); | ||||||
|  | 	spi.len    = __u32(len); | ||||||
|  |  | ||||||
|  | 	int retVal = ioctl(mFid, SPI_IOC_MESSAGE(1), &spi); | ||||||
|  |  | ||||||
|  | 	if (retVal == 0 && latchTime_ns > 0) | ||||||
|  | 	{ | ||||||
|  | 		// The 'latch' time for latching the shifted-value into the leds | ||||||
|  | 		timespec latchTime; | ||||||
|  | 		latchTime.tv_sec  = 0; | ||||||
|  | 		latchTime.tv_nsec = latchTime_ns; | ||||||
|  |  | ||||||
|  | 		// Sleep to latch the leds (only if write succesfull) | ||||||
|  | 		nanosleep(&latchTime, NULL); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return retVal; | ||||||
|  |  | ||||||
|  | } | ||||||
|   | |||||||
| @@ -32,13 +32,26 @@ public: | |||||||
| 	/// | 	/// | ||||||
| 	int open(); | 	int open(); | ||||||
|  |  | ||||||
|  | protected: | ||||||
|  | 	/** | ||||||
|  | 	 * Writes the given bytes/bits to the SPI-device and sleeps the latch time to ensure that the | ||||||
|  | 	 * values are latched. | ||||||
|  | 	 * | ||||||
|  | 	 * @param[in[ len The length of the data | ||||||
|  | 	 * @param[in] vec The data | ||||||
|  | 	 * @param[in] latchTime_ns The latch-time to latch in the values across the SPI-device (negative | ||||||
|  | 	 * means no latch required) [ns] | ||||||
|  | 	 * | ||||||
|  | 	 * @return Zero on succes else negative | ||||||
|  | 	 */ | ||||||
|  | 	int latch(const unsigned len, const char * vec, const int latchTime_ns); | ||||||
|  |  | ||||||
| private: | private: | ||||||
| 	/// The name of the output device | 	/// The name of the output device | ||||||
| 	const std::string mDeviceName; | 	const std::string mDeviceName; | ||||||
| 	/// The used baudrate of the output device | 	/// The used baudrate of the output device | ||||||
| 	const int mBaudRate_Hz; | 	const int mBaudRate_Hz; | ||||||
|  |  | ||||||
| protected: |  | ||||||
| 	/// The File Identifier of the opened output device (or -1 if not opened) | 	/// The File Identifier of the opened output device (or -1 if not opened) | ||||||
| 	int mFid; | 	int mFid; | ||||||
| 	/// The transfer structure for writing to the spi-device | 	/// The transfer structure for writing to the spi-device | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user