<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.extremist.software/index.php?action=history&amp;feed=atom&amp;title=Big_LED_Screen%2Fledtest.c</id>
	<title>Big LED Screen/ledtest.c - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.extremist.software/index.php?action=history&amp;feed=atom&amp;title=Big_LED_Screen%2Fledtest.c"/>
	<link rel="alternate" type="text/html" href="https://wiki.extremist.software/index.php?title=Big_LED_Screen/ledtest.c&amp;action=history"/>
	<updated>2026-04-05T07:57:36Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.39.13</generator>
	<entry>
		<id>https://wiki.extremist.software/index.php?title=Big_LED_Screen/ledtest.c&amp;diff=3077&amp;oldid=prev</id>
		<title>Shkoo: New page: &lt;pre&gt; #include &lt;avr/io.h&gt; #include &lt;avr/interrupt.h&gt; #include &lt;util/delay.h&gt; #include &lt;stdint.h&gt;   /* serial output */ #define MOSI_PINB PB3  /* serial clock */ #define SCK_PINB PB5  /* sl...</title>
		<link rel="alternate" type="text/html" href="https://wiki.extremist.software/index.php?title=Big_LED_Screen/ledtest.c&amp;diff=3077&amp;oldid=prev"/>
		<updated>2009-02-04T02:40:35Z</updated>

		<summary type="html">&lt;p&gt;New page: &amp;lt;pre&amp;gt; #include &amp;lt;avr/io.h&amp;gt; #include &amp;lt;avr/interrupt.h&amp;gt; #include &amp;lt;util/delay.h&amp;gt; #include &amp;lt;stdint.h&amp;gt;   &lt;span dir=&quot;auto&quot;&gt;&lt;span class=&quot;autocomment&quot;&gt;serial output: &lt;/span&gt; #define MOSI_PINB PB3  &lt;span dir=&quot;auto&quot;&gt;&lt;span class=&quot;autocomment&quot;&gt;serial clock: &lt;/span&gt; #define SCK_PINB PB5  /* sl...&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/* serial output */&lt;br /&gt;
#define MOSI_PINB PB3&lt;br /&gt;
&lt;br /&gt;
/* serial clock */&lt;br /&gt;
#define SCK_PINB PB5&lt;br /&gt;
&lt;br /&gt;
/* slave select, needs to be output but is otherwise just ued for&lt;br /&gt;
 * debugging */&lt;br /&gt;
#define SS_PINB PB2&lt;br /&gt;
&lt;br /&gt;
/* pin on PORTB that&amp;#039;s hooked up to the latch output from the buffer board */&lt;br /&gt;
#define LATCH_IN_PINB PB1&lt;br /&gt;
&lt;br /&gt;
/* our output latch port to the daughterboard */&lt;br /&gt;
#define LATCH_OUT_PINB PB0&lt;br /&gt;
&lt;br /&gt;
/* pin on portd that&amp;#039;s hooked up to one of the power pins so we can&lt;br /&gt;
 * synchronize which power pin we&amp;#039;re using */&lt;br /&gt;
#define POWER_PIND PD7&lt;br /&gt;
&lt;br /&gt;
/* output pin that&amp;#039;s 1 when we are on our first power output */&lt;br /&gt;
#define DEBUG_FIRST_POWER_PIND PD6&lt;br /&gt;
&lt;br /&gt;
void ioinit(void)&lt;br /&gt;
{&lt;br /&gt;
  cli();&lt;br /&gt;
&lt;br /&gt;
  // set output pins for output&lt;br /&gt;
  DDRB = _BV(MOSI_PINB) | _BV(SCK_PINB) | _BV(SS_PINB) | _BV(LATCH_OUT_PINB);&lt;br /&gt;
&lt;br /&gt;
  // enable internal pull-up on power pin so it doesn&amp;#039;t cause issues if unconnected&lt;br /&gt;
  // PORTD = _BV(POWER_PIND);&lt;br /&gt;
&lt;br /&gt;
  // debugging output&lt;br /&gt;
  DDRD = _BV(DEBUG_FIRST_POWER_PIND);&lt;br /&gt;
&lt;br /&gt;
  // enable PCI0 interrupt interrupt when latch pin changes&lt;br /&gt;
  PCMSK0 = _BV(PCINT1);&lt;br /&gt;
  // enable PCI2 interrupt when power pin changes (PD7)&lt;br /&gt;
  PCMSK2 = _BV(PCINT23);&lt;br /&gt;
  // enable PCI0 and PCI2 interrupts&lt;br /&gt;
  PCICR = _BV(PCIE0) | _BV(PCIE2);&lt;br /&gt;
&lt;br /&gt;
  // put MOSI up when we&amp;#039;re not clocking out&lt;br /&gt;
  PORTB |= _BV(MOSI_PINB);&lt;br /&gt;
&lt;br /&gt;
  sei ();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static void spistart(void)&lt;br /&gt;
{&lt;br /&gt;
  // start SPI in master mode, at SPI clock&lt;br /&gt;
  // running at CPU frequency / 8&lt;br /&gt;
  SPCR = _BV(SPE) | _BV(MSTR) | _BV(SPR0);&lt;br /&gt;
  SPSR = _BV(SPI2X);&lt;br /&gt;
&lt;br /&gt;
  PORTB &amp;amp;= ~_BV(SS_PINB); // lower slave select (for debugging)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static void spistop(void)&lt;br /&gt;
{&lt;br /&gt;
  SPCR = 0;&lt;br /&gt;
  PORTB |= _BV(SS_PINB); // raise slave select (for debugging)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
unsigned volatile char can_write_out;&lt;br /&gt;
&lt;br /&gt;
unsigned char pow_select; // 0..15 depending on sequence of latching&lt;br /&gt;
unsigned char pow_inverse;&lt;br /&gt;
unsigned char display_count;&lt;br /&gt;
unsigned char inverse;&lt;br /&gt;
unsigned char hilite_byte;&lt;br /&gt;
&lt;br /&gt;
// clock out serial data&lt;br /&gt;
static void writeout(void)&lt;br /&gt;
{&lt;br /&gt;
  unsigned char this_one_inverse;&lt;br /&gt;
  unsigned char this_pow_select;&lt;br /&gt;
  unsigned char byte_count;&lt;br /&gt;
&lt;br /&gt;
  this_pow_select = pow_select;&lt;br /&gt;
  pow_select++;&lt;br /&gt;
  if (pow_select &amp;gt; 15)&lt;br /&gt;
    pow_select = 0;&lt;br /&gt;
&lt;br /&gt;
  sei();&lt;br /&gt;
&lt;br /&gt;
  if (this_pow_select == 0)&lt;br /&gt;
    PORTD |= _BV(DEBUG_FIRST_POWER_PIND);&lt;br /&gt;
&lt;br /&gt;
  if (this_pow_select == pow_inverse) {&lt;br /&gt;
    display_count++;&lt;br /&gt;
    if (display_count &amp;gt; (pow_inverse ? 120 : 30)) {&lt;br /&gt;
      if (inverse) {&lt;br /&gt;
        inverse = 0;&lt;br /&gt;
      } else {&lt;br /&gt;
        pow_inverse++;&lt;br /&gt;
        if (pow_inverse &amp;gt; 15) {&lt;br /&gt;
          pow_inverse = 0;&lt;br /&gt;
          hilite_byte++;&lt;br /&gt;
          if (hilite_byte &amp;gt; (200 / 8)) {&lt;br /&gt;
            hilite_byte = 0;&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
        inverse = 1;&lt;br /&gt;
      }&lt;br /&gt;
      display_count = 0;&lt;br /&gt;
    }&lt;br /&gt;
    this_one_inverse = inverse;&lt;br /&gt;
  } else {&lt;br /&gt;
    this_one_inverse = 0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  // turn off the latch to the daughterboards&lt;br /&gt;
  PORTB &amp;amp;= ~_BV(LATCH_OUT_PINB);&lt;br /&gt;
&lt;br /&gt;
  // and actually clock out&lt;br /&gt;
&lt;br /&gt;
  spistart();&lt;br /&gt;
&lt;br /&gt;
  SPDR = 0b01010101;&lt;br /&gt;
  for (byte_count = 0; byte_count &amp;lt; (200/8); byte_count++) {&lt;br /&gt;
    unsigned register char to_write;&lt;br /&gt;
&lt;br /&gt;
    to_write = this_one_inverse ? ~byte_count : byte_count;&lt;br /&gt;
    to_write = (byte_count == hilite_byte) ? ~to_write : to_write;&lt;br /&gt;
    /* SPIF drops low when the SPI output is finished, so we want to start&lt;br /&gt;
     * the next byte as soon as possible.&lt;br /&gt;
     *&lt;br /&gt;
     * This requires any work that needs to be done to gather the value to&lt;br /&gt;
     * write (such as loading it in a register) to be done before we wait&lt;br /&gt;
     * for SPIF to drop */&lt;br /&gt;
    __asm__(&lt;br /&gt;
            &amp;quot;.spi_not_ready:&amp;quot;                      &amp;quot;\n\t&amp;quot;&lt;br /&gt;
            &amp;quot;in __tmp_reg__,%[spsr]&amp;quot;               &amp;quot;\n\t&amp;quot;&lt;br /&gt;
            &amp;quot;sbrs __tmp_reg__, %[spif]&amp;quot;            &amp;quot;\n\t&amp;quot;&lt;br /&gt;
            &amp;quot;rjmp .spi_not_ready&amp;quot;                  &amp;quot;\n\t&amp;quot;&lt;br /&gt;
            &amp;quot;out %[spdr], %[towrite]&amp;quot;              &amp;quot;\n\t&amp;quot;&lt;br /&gt;
            ::&lt;br /&gt;
            [spsr] &amp;quot;I&amp;quot; (_SFR_IO_ADDR(SPSR)),&lt;br /&gt;
            [spif] &amp;quot;I&amp;quot; (SPIF),&lt;br /&gt;
            [spdr] &amp;quot;I&amp;quot; (_SFR_IO_ADDR(SPDR)),&lt;br /&gt;
            [towrite] &amp;quot;r&amp;quot; (to_write)&lt;br /&gt;
            );&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  spistop();&lt;br /&gt;
  PORTD &amp;amp;= ~_BV(DEBUG_FIRST_POWER_PIND);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
ISR(PCINT0_vect) /* &amp;quot;PCI0&amp;quot; interrupts */&lt;br /&gt;
{&lt;br /&gt;
  // latch pin changed.  write out serial if we&amp;#039;re not in the middle of it already&lt;br /&gt;
  if (!can_write_out) return;&lt;br /&gt;
&lt;br /&gt;
  // output latch pin to activate the new values we shifted in last time:&lt;br /&gt;
  PORTB |= _BV(LATCH_OUT_PINB);&lt;br /&gt;
  // (it&amp;#039;s turned off within &amp;quot;writeout&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
  // mark writing out as busy, and then enable interrupts so we can go on with life&lt;br /&gt;
  can_write_out = 0;  &lt;br /&gt;
&lt;br /&gt;
  // now, emit our data&lt;br /&gt;
  writeout();&lt;br /&gt;
&lt;br /&gt;
  // we&amp;#039;re done! re-enable writing out&lt;br /&gt;
  can_write_out = 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// PCINT23 toggled&lt;br /&gt;
ISR(PCINT2_vect)&lt;br /&gt;
{&lt;br /&gt;
  if (PIND &amp;amp; _BV(POWER_PIND)) {&lt;br /&gt;
    // low-&amp;gt;high transition at the beginning of the power signal.&lt;br /&gt;
    // we get a latch spike at approximately this time, so we have to figure out whether&lt;br /&gt;
    // we got that or not in order to avoid the race condition:&lt;br /&gt;
    if (can_write_out == 0) {&lt;br /&gt;
      // we&amp;#039;re busy writing out, hopefully this is frame 0.  reset to frame 1.&lt;br /&gt;
      pow_select = 1;&lt;br /&gt;
    } else {&lt;br /&gt;
      // haven&amp;#039;t started to write out frame 0 yet; next frame is 0&lt;br /&gt;
      pow_select = 0;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(void) &lt;br /&gt;
{&lt;br /&gt;
  can_write_out = 1;&lt;br /&gt;
  ioinit();&lt;br /&gt;
&lt;br /&gt;
  for (;;) {&lt;br /&gt;
    can_write_out = 2;&lt;br /&gt;
    _delay_ms(100);&lt;br /&gt;
    cli();&lt;br /&gt;
    if (can_write_out == 2) {&lt;br /&gt;
      // we didn&amp;#039;t receive any input on the latch pin; write out every 100 ms&lt;br /&gt;
      // for debugging purposes&lt;br /&gt;
      writeout();&lt;br /&gt;
    }&lt;br /&gt;
    sei();&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Shkoo</name></author>
	</entry>
</feed>