rpi-rgb-led-matrix icon indicating copy to clipboard operation
rpi-rgb-led-matrix copied to clipboard

Meta bug: Support HUB08/HUB12

Open hzeller opened this issue 7 years ago • 11 comments

Hub12 is very similar to Hub75, but the Output-enable has positive level (I think), and of course we can control many more panels with the outputs, as we only need Red or Red/Green and the free GPIO pins can be used for more panels.

So needed to implement

  • Expand the idea of hardware mapping in a way that we naturally can represent things with less colors
  • Make OE switchable to positive logic.
  • Explore what other PixelMappers are needed to support multiplexing modes on these panels.
  • Maybe build a breakout PCB to connect these panels (there can be 3x as many Hub12 panels connected to a Pi than RGB).

This is a meta bug as this has come up sufficiently often in separate bug entries, but it is easier to collect collected changes on a single one.

Some bugs requesting this are #527 #400 #270 #254 #208 #99

hzeller avatar Feb 25 '18 20:02 hzeller

Hi Hzeller,

I have written a multiplex mapper for HUB12 panel and have run it successfully (so far only on a single panel. Should work multiple panels as well). Will test the same on multiple panels and will let you know. Please note that mine is a 32x16 HUB12 single color panel. My panel is internally divided into four parts (128x4). I have written this mapper by keeping my panel in mind and its working fine. Also, I have enabled the sub-panel flag in lib Makefile.

In case if you feel then you can include this mapper into your library so that others can also use it in case if they have the same panel.

`class P10SingleColorHUB12Mapper : public MultiplexMapperBase { public: P10SingleColorHUB12Mapper(const char *name) : MultiplexMapperBase(name, 4){}

void MapSinglePanel(int x, int y, int *matrix_x, int *matrix_y) const {
	if (y / 4 == 0) {
		*matrix_y = y % 4;
		if (x / 8 == 0) {
			*matrix_x = x + 24;
		} else if (x / 8 == 1) {
			*matrix_x = x + 48;
		} else if (x / 8 == 2) {
			*matrix_x = x + 72;
		} else if (x / 8 == 3) {
			*matrix_x = x + 96;
		}
	} else if (y / 4 == 1) {
		*matrix_y = y % 4;
		if (x / 8 == 0) {
			*matrix_x = x + 16;
		} else if (x / 8 == 1) {
			*matrix_x = x + 40;
		} else if (x / 8 == 2) {
			*matrix_x = x + 64;
		} else if (x / 8 == 3) {
			*matrix_x = x + 88;
		}

	} else if (y / 4 == 2) {
		*matrix_y = y % 4;
		if (x / 8 == 0) {
			*matrix_x = x + 8;
		} else if (x / 8 == 1) {
			*matrix_x = x + 32;
		} else if (x / 8 == 2) {
			*matrix_x = x + 56;
		} else if (x / 8 == 3) {
			*matrix_x = x + 80;
		}

	} else if (y / 4 == 3) {
		*matrix_y = y % 4;
		if (x / 8 == 0) {
			*matrix_x = x;
		} else if (x / 8 == 1) {
			*matrix_x = x + 24;
		} else if (x / 8 == 2) {
			*matrix_x = x + 48;
		} else if (x / 8 == 3) {
			*matrix_x = x + 72;
		}
	}
}

};

static MuxMapperList *CreateMultiplexMapperList() { MuxMapperList *result = new MuxMapperList();

// Here, register all multiplex mappers from above. result->push_back(new StripeMultiplexMapper()); result->push_back(new CheckeredMultiplexMapper()); result->push_back(new SpiralMultiplexMapper()); result->push_back(new ZStripeMultiplexMapper("ZStripe", 0, 8)); result->push_back(new ZStripeMultiplexMapper("ZnMirrorZStripe", 4, 4)); result->push_back(new CoremanMapper()); result->push_back(new P10SingleColorHUB12Mapper("P10SingleColor"));

return result; } `

lbnshrivas avatar Jun 07 '18 17:06 lbnshrivas

Apart from above changes I have made the following changes as well :

  • Have changed the Assertion statement in framebuffer.cc:209 to allow 4 rows. Currently its only allowing 8 rows or more than that. Since my panel's internal mapping is 128x4 so I need to make this change as well to allow less than 8 rows.

  • Have made OE high through software by changing the code in gpio.cc #define PWM_CTL_POLA1 (0<<4) // CH1 Polarity (0=(0=low 1=high) 1=(1=low 0=high)

virtual void SendPulse(int time_spec_number) { io_->SetBits(bits_); Timers::sleep_nanos(nano_specs_[time_spec_number]); io_->ClearBits(bits_); }

lbnshrivas avatar Jun 07 '18 18:06 lbnshrivas

Since quite a few changes are needed to make this adaptable to Hub12/monochrome, Maybe the library needs forked so its rpi-hub12-led-matrix? or rpi-monochrome-led-matrix?

Not sure if these tiles are fast enough to do a good enough greyscale, but if not, then maybe dithering libraries are needed to convert the RGB24bit to R/G/B summing to dithering like they did in the old days of computers.

Sorry just kind of spitballing here.

thetechknight avatar Oct 03 '18 19:10 thetechknight

hello everyone, Thank you Mr. Zeller and everyone else who has contributed to make this library.

I am newbie to the world of rPi.

I came across some very cheap p10 modules with Hub12 interfaces. I am keen to interface it with a 40-pin rPI.

After having gone through a lot of google searches I have finally ended up on this Git Page and this issue(#531). I feel that I am very close to getting the panels to work with the first gen of 40-pin rPI.

I have taken care of the OE, Gnd, A, B, Clock and SCLK pins. I am not able to figure out where to connect the Data pin. For now I have connected it to the R1 pin.

I am getting a lot of gibberish on the screen. But when I scroll the demo, the gibberish scrolls across the screen smoothly.

So to troubleshoot, I have multiple places to look into. Before getting into it, just wanted to know if the changes suggested by Mr. Ibnshrivas are already a part of the library..or do I need to make those changes manually.

regards, Jawed

jawedsoft avatar Mar 16 '20 06:03 jawedsoft

yes, data is essentially one of the color pins. The HUB12 are typically only one (red) or two (red/green) colors, so they have much less data lines. I am not sure if they are also segmented in two half-panels as the HUB75, but of not, then there will be only one or two data lines.

My suspicion is that the digital levels for some of the signals are inverted, see above in the thread. Should be fairly straight-forward to add, I just didn't get around to it because I don't own a HUB12 panel, so couldn't really test.

hzeller avatar Mar 16 '20 06:03 hzeller

Apart from above changes I have made the following changes as well :

  • Have changed the Assertion statement in framebuffer.cc:209 to allow 4 rows. Currently its only allowing 8 rows or more than that. Since my panel's internal mapping is 128x4 so I need to make this change as well to allow less than 8 rows.
  • Have made OE high through software by changing the code in gpio.cc #define PWM_CTL_POLA1 (0<<4) // CH1 Polarity (0=(0=low 1=high) 1=(1=low 0=high)

virtual void SendPulse(int time_spec_number) { io_->SetBits(bits_); Timers::sleep_nanos(nano_specs_[time_spec_number]); io_->ClearBits(bits_); }

@lbnshrivas thanks for you work on this . I tried setting the following as per your comments

  • multiplex mapper
  • did not find the Assertion in framebuffer.cc:209 . I assuming the code has changed since your comment
  • PWM_CTL_POLA1 define
  • SendPulse change

Unfortunately am unable to get anything useful working . Just see some leds light up.When I kill the test(ctrl+c) the leds stay on . I have connected the PI3B+ pins directly to the Hub12. Also am using Raspbian on my PI

My panel setup sounds similar to yours . 32x16 (2 panels) with following pins on HUB12 , which I have connected as per the diagram here . I have attached R0,G0 to R1 and G1. Any thoughts would be very helpful

A B C CK ST R0 G0 D


OE GND GND GND GND GND GND

smitkant avatar Aug 22 '20 13:08 smitkant

@hzeller have been trying to understand the library better . you've done a great job with this . Wanted to understand the multiplex mapper a bit better , especially the MapSinglePanel function . Could you point me in teed ruction to understand this and led multiplexing in general a bit better. Thanks a ton.

smitkant avatar Aug 23 '20 02:08 smitkant

Hi Hzeller,

I have written a multiplex mapper for HUB12 panel and have run it successfully (so far only on a single panel. Should work multiple panels as well). Will test the same on multiple panels and will let you know. Please note that mine is a 32x16 HUB12 single color panel. My panel is internally divided into four parts (128x4). I have written this mapper by keeping my panel in mind and its working fine. Also, I have enabled the sub-panel flag in lib Makefile.

In case if you feel then you can include this mapper into your library so that others can also use it in case if they have the same panel.

`class P10SingleColorHUB12Mapper : public MultiplexMapperBase { public: P10SingleColorHUB12Mapper(const char *name) : MultiplexMapperBase(name, 4){}

void MapSinglePanel(int x, int y, int *matrix_x, int *matrix_y) const {
	if (y / 4 == 0) {
		*matrix_y = y % 4;
		if (x / 8 == 0) {
			*matrix_x = x + 24;
		} else if (x / 8 == 1) {
			*matrix_x = x + 48;
		} else if (x / 8 == 2) {
			*matrix_x = x + 72;
		} else if (x / 8 == 3) {
			*matrix_x = x + 96;
		}
	} else if (y / 4 == 1) {
		*matrix_y = y % 4;
		if (x / 8 == 0) {
			*matrix_x = x + 16;
		} else if (x / 8 == 1) {
			*matrix_x = x + 40;
		} else if (x / 8 == 2) {
			*matrix_x = x + 64;
		} else if (x / 8 == 3) {
			*matrix_x = x + 88;
		}

	} else if (y / 4 == 2) {
		*matrix_y = y % 4;
		if (x / 8 == 0) {
			*matrix_x = x + 8;
		} else if (x / 8 == 1) {
			*matrix_x = x + 32;
		} else if (x / 8 == 2) {
			*matrix_x = x + 56;
		} else if (x / 8 == 3) {
			*matrix_x = x + 80;
		}

	} else if (y / 4 == 3) {
		*matrix_y = y % 4;
		if (x / 8 == 0) {
			*matrix_x = x;
		} else if (x / 8 == 1) {
			*matrix_x = x + 24;
		} else if (x / 8 == 2) {
			*matrix_x = x + 48;
		} else if (x / 8 == 3) {
			*matrix_x = x + 72;
		}
	}
}

};

static MuxMapperList *CreateMultiplexMapperList() { MuxMapperList *result = new MuxMapperList();

// Here, register all multiplex mappers from above. result->push_back(new StripeMultiplexMapper()); result->push_back(new CheckeredMultiplexMapper()); result->push_back(new SpiralMultiplexMapper()); result->push_back(new ZStripeMultiplexMapper("ZStripe", 0, 8)); result->push_back(new ZStripeMultiplexMapper("ZnMirrorZStripe", 4, 4)); result->push_back(new CoremanMapper()); result->push_back(new P10SingleColorHUB12Mapper("P10SingleColor"));

return result; } `

Hi, thnaks for making this. is this now implemented in the libary?

threiner avatar Jun 07 '21 01:06 threiner

HUB12 has not been implemented in this library (yet? I don't have a HUB12 to test, so we'd need someone who has to send a pull request.)

hzeller avatar Jun 07 '21 01:06 hzeller

I have 6 boards here so i ould test it.

threiner avatar Jun 07 '21 01:06 threiner

Hi Hzeller,

I have written a multiplex mapper for HUB12 panel and have run it successfully (so far only on a single panel. Should work multiple panels as well). Will test the same on multiple panels and will let you know. Please note that mine is a 32x16 HUB12 single color panel. My panel is internally divided into four parts (128x4). I have written this mapper by keeping my panel in mind and its working fine. Also, I have enabled the sub-panel flag in lib Makefile.

In case if you feel then you can include this mapper into your library so that others can also use it in case if they have the same panel.

`class P10SingleColorHUB12Mapper : public MultiplexMapperBase { public: P10SingleColorHUB12Mapper(const char *name) : MultiplexMapperBase(name, 4){}

void MapSinglePanel(int x, int y, int *matrix_x, int *matrix_y) const {
	if (y / 4 == 0) {
		*matrix_y = y % 4;
		if (x / 8 == 0) {
			*matrix_x = x + 24;
		} else if (x / 8 == 1) {
			*matrix_x = x + 48;
		} else if (x / 8 == 2) {
			*matrix_x = x + 72;
		} else if (x / 8 == 3) {
			*matrix_x = x + 96;
		}
	} else if (y / 4 == 1) {
		*matrix_y = y % 4;
		if (x / 8 == 0) {
			*matrix_x = x + 16;
		} else if (x / 8 == 1) {
			*matrix_x = x + 40;
		} else if (x / 8 == 2) {
			*matrix_x = x + 64;
		} else if (x / 8 == 3) {
			*matrix_x = x + 88;
		}

	} else if (y / 4 == 2) {
		*matrix_y = y % 4;
		if (x / 8 == 0) {
			*matrix_x = x + 8;
		} else if (x / 8 == 1) {
			*matrix_x = x + 32;
		} else if (x / 8 == 2) {
			*matrix_x = x + 56;
		} else if (x / 8 == 3) {
			*matrix_x = x + 80;
		}

	} else if (y / 4 == 3) {
		*matrix_y = y % 4;
		if (x / 8 == 0) {
			*matrix_x = x;
		} else if (x / 8 == 1) {
			*matrix_x = x + 24;
		} else if (x / 8 == 2) {
			*matrix_x = x + 48;
		} else if (x / 8 == 3) {
			*matrix_x = x + 72;
		}
	}
}

};

static MuxMapperList *CreateMultiplexMapperList() { MuxMapperList *result = new MuxMapperList();

// Here, register all multiplex mappers from above. result->push_back(new StripeMultiplexMapper()); result->push_back(new CheckeredMultiplexMapper()); result->push_back(new SpiralMultiplexMapper()); result->push_back(new ZStripeMultiplexMapper("ZStripe", 0, 8)); result->push_back(new ZStripeMultiplexMapper("ZnMirrorZStripe", 4, 4)); result->push_back(new CoremanMapper()); result->push_back(new P10SingleColorHUB12Mapper("P10SingleColor"));

return result; } `

sir i have added the mapper code provided by you but in demo i am unable to see the optional map u have given do i need to make the file again after altering the library? please guide me through the library updation with your custom map

thanks..

suryaprakhya52 avatar Feb 11 '25 11:02 suryaprakhya52