<commit_before>#ifndef __INC_CHIPSETS_H
#define __INC_CHIPSETS_H

#include "pixeltypes.h"

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// DeepPixel controller class - takes data/clock/select pin values (N.B. should take an SPI definition?)
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

template <uint8_t DATA_PIN, uint8_t CLOCK_PIN, EOrder RGB_ORDER = RGB, uint8_t SPI_SPEED = DATA_RATE_MHZ(10)>
class DeepPixelController : public CLEDController {
	typedef SPIOutput<DATA_PIN, CLOCK_PIN, SPI_SPEED> SPI;
	SPI mSPI;

	void writeStart() { mSPI.writeWord(0xFFFF); mSPI.writeWord(0xFFFF); }
	void writeStop() { mSPI.writeWord(0x0000); mSPI.writeWord(0x0000); }

	inline void writeLed(uint8_t r, uint8_t g, uint8_t b) __attribute__((always_inline)) {
		mSPI.writeByte(0xFF); mSPI.writeByte(r); mSPI.writeByte(g); mSPI.writeByte(b);
	}

public:
	DeepPixelController() {}

	virtual void init() {
		mSPI.init();
	}

	virtual void clearLeds(int nLeds) {
		showColor(CRGB(0,0,0), nLeds, CRGB(0,0,0));
	}

	virtual void showColor(const struct CRGB & data, int nLeds, CRGB scale) {
		PixelController<RGB_ORDER> pixels(data, nLeds, scale, getDither());

		mSPI.select();

		writeStart();
		while(nLeds--) {
			writeLed(pixels.loadAndScale0(), pixels.loadAndScale1(), pixels.loadAndScale2());
			pixels.stepDithering();
		}
		writeStop();

		mSPI.waitFully();
		mSPI.release();
	}

	virtual void show(const struct CRGB *data, int nLeds, CRGB scale) {
		PixelController<RGB_ORDER> pixels(data, nLeds, scale, getDither());

		mSPI.select();

		writeStart();
		for(int i = 0; i < nLeds; i++) {
			writeLed(pixels.loadAndScale0(), pixels.loadAndScale1(), pixels.loadAndScale2());
			pixels.advanceData();
			pixels.stepDithering();
		}
		writeStop();

		mSPI.release();
	}

#ifdef SUPPORT_ARGB
	virtual void show(const struct CRGB *data, int nLeds, CRGB scale) {
		PixelController<RGB_ORDER> pixels(data, nLeds,, scale, getDither());

		mSPI.select();

		writeBoundary();
		for(int i = 0; i < nLeds; i++) {
			writeLed(pixels.loadAndScale0(), pixels.loadAndScale1(), pixels.loadAndScale2());
			pixels.advanceData();
			pixels.stepDithering();
		}
		writeBoundary();

		mSPI.release();
	}
#endif
};


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// LPD8806 controller class - takes data/clock/select pin values (N.B. should take an SPI definition?)
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

template <uint8_t DATA_PIN, uint8_t CLOCK_PIN, EOrder RGB_ORDER = RGB,  uint8_t SPI_SPEED = DATA_RATE_MHZ(12) >
class LPD8806Controller : public CLEDController {
	typedef SPIOutput<DATA_PIN, CLOCK_PIN, SPI_SPEED> SPI;

	class LPD8806_ADJUST {
	public:
		// LPD8806 spec wants the high bit of every rgb data byte sent out to be set.
		__attribute__((always_inline)) inline static uint8_t adjust(register uint8_t data) { return ((data>>1) | 0x80) + ((data && (data<254)) & 0x01); }
		__attribute__((always_inline)) inline static void postBlock(int len) {
			SPI::writeBytesValueRaw(0, ((len*3+63)>>6));
		}

	};

	SPI mSPI;
	int mClearedLeds;

	void checkClear(int nLeds) {
		if(nLeds > mClearedLeds) {
			clearLine(nLeds);
			mClearedLeds = nLeds;
		}
	}

	void clearLine(int nLeds) {
		int n = ((nLeds*3  + 63) >> 6);
		mSPI.writeBytesValue(0, n);
	}
public:
	LPD8806Controller()  {}
	virtual void init() {
		mSPI.init();
		mClearedLeds = 0;
	}

	virtual void clearLeds(int nLeds) {
		mSPI.select();
		mSPI.writeBytesValueRaw(0x80, nLeds * 3);
		mSPI.writeBytesValueRaw(0, ((nLeds*3+63)>>6));
		mSPI.release();
	}

protected:

	virtual void showColor(const struct CRGB & data, int nLeds, CRGB scale) {
		mSPI.template writePixels<0, LPD8806_ADJUST, RGB_ORDER>(PixelController<RGB_ORDER>(data, nLeds, scale, getDither()));
	}

	virtual void show(const struct CRGB *data, int nLeds, CRGB scale) {
		// TODO rgb-ize scale
		mSPI.template writePixels<0, LPD8806_ADJUST, RGB_ORDER>(PixelController<RGB_ORDER>(data, nLeds, scale, getDither()));
	}

#ifdef SUPPORT_ARGB
	virtual void show(const struct CARGB *data, int nLeds, uint8_t scale) {
		checkClear(nLeds);
		mSPI.template writePixels<0, LPD8806_ADJUST, RGB_ORDER>(PixelController<RGB_ORDER>(data, nLeds, scale, getDither()));
	}
#endif
};


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// WS2801 definition - takes data/clock/select pin values (N.B. should take an SPI definition?)
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

template <uint8_t DATA_PIN, uint8_t CLOCK_PIN, EOrder RGB_ORDER = RGB, uint8_t SPI_SPEED = DATA_RATE_MHZ(1)>
class WS2801Controller : public CLEDController {
	typedef SPIOutput<DATA_PIN, CLOCK_PIN, SPI_SPEED> SPI;
	SPI mSPI;
	CMinWait<1000>  mWaitDelay;
public:
	WS2801Controller() {}

	virtual void init() {
		mSPI.init();
	    mWaitDelay.mark();
	}

	virtual void clearLeds(int nLeds) {
		mWaitDelay.wait();
		mSPI.writeBytesValue(0, nLeds*3);
		mWaitDelay.mark();
	}

protected:

	virtual void showColor(const struct CRGB & data, int nLeds, CRGB scale) {
		mWaitDelay.wait();
		mSPI.template writePixels<0, DATA_NOP, RGB_ORDER>(PixelController<RGB_ORDER>(data, nLeds, scale, getDither()));
		mWaitDelay.mark();
	}

	virtual void show(const struct CRGB *data, int nLeds, CRGB scale) {
		mWaitDelay.wait();
		mSPI.template writePixels<0, DATA_NOP, RGB_ORDER>(PixelController<RGB_ORDER>(data, nLeds, scale, getDither()));
		mWaitDelay.mark();
	}

#ifdef SUPPORT_ARGB
	virtual void show(const struct CRGB *data, int nLeds, CRGB scale) {
		mWaitDelay.wait();
		mSPI.template writePixels<0, DATA_NOP, RGB_ORDER>(PixelController<RGB_ORDER>(data, nLeds, scale, getDither()));
		mWaitDelay.mark();
	}
#endif
};

template <uint8_t DATA_PIN, uint8_t CLOCK_PIN, EOrder RGB_ORDER = RGB, uint8_t SPI_SPEED = DATA_RATE_MHZ(25)>
class WS2803Controller : public WS2801Controller<DATA_PIN, CLOCK_PIN, RGB_ORDER, SPI_SPEED> {};

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// APA102 definition - takes data/clock/select pin values (N.B. should take an SPI definition?)
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

template <uint8_t DATA_PIN, uint8_t CLOCK_PIN, EOrder RGB_ORDER = BGR, uint8_t SPI_SPEED = DATA_RATE_MHZ(24)>
class APA102Controller : public CLEDController {
	typedef SPIOutput<DATA_PIN, CLOCK_PIN, SPI_SPEED> SPI;
	SPI mSPI;

	void startBoundary() { mSPI.writeWord(0); mSPI.writeWord(0); }
	void endBoundary(int nLeds) { int nBytes = (nLeds/16); do { mSPI.writeByte(0xFF); } while(nBytes--); }

	inline void writeLed(uint8_t b0, uint8_t b1, uint8_t b2) __attribute__((always_inline)) {
		mSPI.writeByte(0xFF); mSPI.writeByte(b0); mSPI.writeByte(b1); mSPI.writeByte(b2);
	}

public:
	APA102Controller() {}

	virtual void init() {
		mSPI.init();
	}

	virtual void clearLeds(int nLeds) {
		showColor(CRGB(0,0,0), nLeds, CRGB(0,0,0));
	}

protected:

	virtual void showColor(const struct CRGB & data, int nLeds, CRGB scale) {
		PixelController<RGB_ORDER> pixels(data, nLeds, scale, getDither());

		mSPI.select();

		startBoundary();
		for(int i = 0; i < nLeds; i++) {
			writeLed(pixels.loadAndScale0(), pixels.loadAndScale1(), pixels.loadAndScale2());<commit_msg>More accurate end frame for APA102.<commit_after>#ifndef __INC_CHIPSETS_H
#define __INC_CHIPSETS_H

#include "pixeltypes.h"

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// DeepPixel controller class - takes data/clock/select pin values (N.B. should take an SPI definition?)
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

template <uint8_t DATA_PIN, uint8_t CLOCK_PIN, EOrder RGB_ORDER = RGB, uint8_t SPI_SPEED = DATA_RATE_MHZ(10)>
class DeepPixelController : public CLEDController {
	typedef SPIOutput<DATA_PIN, CLOCK_PIN, SPI_SPEED> SPI;
	SPI mSPI;

	void writeStart() { mSPI.writeWord(0xFFFF); mSPI.writeWord(0xFFFF); }
	void writeStop() { mSPI.writeWord(0x0000); mSPI.writeWord(0x0000); }

	inline void writeLed(uint8_t r, uint8_t g, uint8_t b) __attribute__((always_inline)) {
		mSPI.writeByte(0xFF); mSPI.writeByte(r); mSPI.writeByte(g); mSPI.writeByte(b);
	}

public:
	DeepPixelController() {}

	virtual void init() {
		mSPI.init();
	}

	virtual void clearLeds(int nLeds) {
		showColor(CRGB(0,0,0), nLeds, CRGB(0,0,0));
	}

	virtual void showColor(const struct CRGB & data, int nLeds, CRGB scale) {
		PixelController<RGB_ORDER> pixels(data, nLeds, scale, getDither());

		mSPI.select();

		writeStart();
		while(nLeds--) {
			writeLed(pixels.loadAndScale0(), pixels.loadAndScale1(), pixels.loadAndScale2());
			pixels.stepDithering();
		}
		writeStop();

		mSPI.waitFully();
		mSPI.release();
	}

	virtual void show(const struct CRGB *data, int nLeds, CRGB scale) {
		PixelController<RGB_ORDER> pixels(data, nLeds, scale, getDither());

		mSPI.select();

		writeStart();
		for(int i = 0; i < nLeds; i++) {
			writeLed(pixels.loadAndScale0(), pixels.loadAndScale1(), pixels.loadAndScale2());
			pixels.advanceData();
			pixels.stepDithering();
		}
		writeStop();

		mSPI.release();
	}

#ifdef SUPPORT_ARGB
	virtual void show(const struct CRGB *data, int nLeds, CRGB scale) {
		PixelController<RGB_ORDER> pixels(data, nLeds,, scale, getDither());

		mSPI.select();

		writeBoundary();
		for(int i = 0; i < nLeds; i++) {
			writeLed(pixels.loadAndScale0(), pixels.loadAndScale1(), pixels.loadAndScale2());
			pixels.advanceData();
			pixels.stepDithering();
		}
		writeBoundary();

		mSPI.release();
	}
#endif
};


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// LPD8806 controller class - takes data/clock/select pin values (N.B. should take an SPI definition?)
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

template <uint8_t DATA_PIN, uint8_t CLOCK_PIN, EOrder RGB_ORDER = RGB,  uint8_t SPI_SPEED = DATA_RATE_MHZ(12) >
class LPD8806Controller : public CLEDController {
	typedef SPIOutput<DATA_PIN, CLOCK_PIN, SPI_SPEED> SPI;

	class LPD8806_ADJUST {
	public:
		// LPD8806 spec wants the high bit of every rgb data byte sent out to be set.
		__attribute__((always_inline)) inline static uint8_t adjust(register uint8_t data) { return ((data>>1) | 0x80) + ((data && (data<254)) & 0x01); }
		__attribute__((always_inline)) inline static void postBlock(int len) {
			SPI::writeBytesValueRaw(0, ((len*3+63)>>6));
		}

	};

	SPI mSPI;
	int mClearedLeds;

	void checkClear(int nLeds) {
		if(nLeds > mClearedLeds) {
			clearLine(nLeds);
			mClearedLeds = nLeds;
		}
	}

	void clearLine(int nLeds) {
		int n = ((nLeds*3  + 63) >> 6);
		mSPI.writeBytesValue(0, n);
	}
public:
	LPD8806Controller()  {}
	virtual void init() {
		mSPI.init();
		mClearedLeds = 0;
	}

	virtual void clearLeds(int nLeds) {
		mSPI.select();
		mSPI.writeBytesValueRaw(0x80, nLeds * 3);
		mSPI.writeBytesValueRaw(0, ((nLeds*3+63)>>6));
		mSPI.release();
	}

protected:

	virtual void showColor(const struct CRGB & data, int nLeds, CRGB scale) {
		mSPI.template writePixels<0, LPD8806_ADJUST, RGB_ORDER>(PixelController<RGB_ORDER>(data, nLeds, scale, getDither()));
	}

	virtual void show(const struct CRGB *data, int nLeds, CRGB scale) {
		// TODO rgb-ize scale
		mSPI.template writePixels<0, LPD8806_ADJUST, RGB_ORDER>(PixelController<RGB_ORDER>(data, nLeds, scale, getDither()));
	}

#ifdef SUPPORT_ARGB
	virtual void show(const struct CARGB *data, int nLeds, uint8_t scale) {
		checkClear(nLeds);
		mSPI.template writePixels<0, LPD8806_ADJUST, RGB_ORDER>(PixelController<RGB_ORDER>(data, nLeds, scale, getDither()));
	}
#endif
};


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// WS2801 definition - takes data/clock/select pin values (N.B. should take an SPI definition?)
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

template <uint8_t DATA_PIN, uint8_t CLOCK_PIN, EOrder RGB_ORDER = RGB, uint8_t SPI_SPEED = DATA_RATE_MHZ(1)>
class WS2801Controller : public CLEDController {
	typedef SPIOutput<DATA_PIN, CLOCK_PIN, SPI_SPEED> SPI;
	SPI mSPI;
	CMinWait<1000>  mWaitDelay;
public:
	WS2801Controller() {}

	virtual void init() {
		mSPI.init();
	    mWaitDelay.mark();
	}

	virtual void clearLeds(int nLeds) {
		mWaitDelay.wait();
		mSPI.writeBytesValue(0, nLeds*3);
		mWaitDelay.mark();
	}

protected:

	virtual void showColor(const struct CRGB & data, int nLeds, CRGB scale) {
		mWaitDelay.wait();
		mSPI.template writePixels<0, DATA_NOP, RGB_ORDER>(PixelController<RGB_ORDER>(data, nLeds, scale, getDither()));
		mWaitDelay.mark();
	}

	virtual void show(const struct CRGB *data, int nLeds, CRGB scale) {
		mWaitDelay.wait();
		mSPI.template writePixels<0, DATA_NOP, RGB_ORDER>(PixelController<RGB_ORDER>(data, nLeds, scale, getDither()));
		mWaitDelay.mark();
	}

#ifdef SUPPORT_ARGB
	virtual void show(const struct CRGB *data, int nLeds, CRGB scale) {
		mWaitDelay.wait();
		mSPI.template writePixels<0, DATA_NOP, RGB_ORDER>(PixelController<RGB_ORDER>(data, nLeds, scale, getDither()));
		mWaitDelay.mark();
	}
#endif
};

template <uint8_t DATA_PIN, uint8_t CLOCK_PIN, EOrder RGB_ORDER = RGB, uint8_t SPI_SPEED = DATA_RATE_MHZ(25)>
class WS2803Controller : public WS2801Controller<DATA_PIN, CLOCK_PIN, RGB_ORDER, SPI_SPEED> {};

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// APA102 definition - takes data/clock/select pin values (N.B. should take an SPI definition?)
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

template <uint8_t DATA_PIN, uint8_t CLOCK_PIN, EOrder RGB_ORDER = BGR, uint8_t SPI_SPEED = DATA_RATE_MHZ(24)>
class APA102Controller : public CLEDController {
	typedef SPIOutput<DATA_PIN, CLOCK_PIN, SPI_SPEED> SPI;
	SPI mSPI;

	void startBoundary() { mSPI.writeWord(0); mSPI.writeWord(0); }
	void endBoundary(int nLeds) { int nBytes = (nLeds/64); do { mSPI.writeByte(0xFF); mSPI.writeByte(0x00); mSPI.writeByte(0x00); mSPI.writeByte(0x00); } while(nBytes--); }

	inline void writeLed(uint8_t b0, uint8_t b1, uint8_t b2) __attribute__((always_inline)) {
		mSPI.writeByte(0xFF); mSPI.writeByte(b0); mSPI.writeByte(b1); mSPI.writeByte(b2);
	}

public:
	APA102Controller() {}

	virtual void init() {
		mSPI.init();
	}

	virtual void clearLeds(int nLeds) {
		showColor(CRGB(0,0,0), nLeds, CRGB(0,0,0));
	}

protected:

	virtual void showColor(const struct CRGB & data, int nLeds, CRGB scale) {
		PixelController<RGB_ORDER> pixels(data, nLeds, scale, getDither());

		mSPI.select();

		startBoundary();
		for(int i = 0; i < nLeds; i++) {
			writeLed(pixels.loadAndScale0(), pixels.loadAndScale1(), pixels.loadAndScale2());
{'fraction_non_alphanumeric': 0.25205814252636993, 'fraction_numerical': 0.024954978132235656, 'mean_word_length': 2.5885068082160165, 'pattern_counts': {'":': 0, '<': 65, '<?xml version=': 0, '>': 75, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3244384', 'n_tokens_mistral': 5601, 'n_tokens_neox': 5124, 'n_words': 1139}