summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--shiftbrite.c141
-rw-r--r--shiftbrite.h5
2 files changed, 146 insertions, 0 deletions
diff --git a/shiftbrite.c b/shiftbrite.c
new file mode 100644
index 0000000..5cc5b82
--- /dev/null
+++ b/shiftbrite.c
@@ -0,0 +1,141 @@
+/*
+ * Simple ShiftBrite interface code for remoodlamp firmware
+ * Copyright 2012 (C) Johannes Kroll <jkroll at lavabit com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with This program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <avr/interrupt.h>
+#include <avr/io.h>
+#include <stdint.h>
+#include <string.h>
+#include <util/delay.h>
+
+// shiftbrites connected to header labeled as 'aux', setup:
+// PC0 -> CI (clock)
+// PC1 -> LI (latch)
+// PC2 -> DI (data)
+
+#define SBCI PC0
+#define SBLI PC1
+#define SBDI PC2
+
+#define MAXSHIFTBRITES 16
+
+
+typedef struct rgb
+{
+ uint16_t r, g, b; // 10-bit values
+} rgb_t;
+
+static volatile rgb_t sb_colors[MAXSHIFTBRITES];
+
+// number of connected shiftbrites
+// todo: create a command to make this value configurable
+static volatile uint8_t sb_num_shiftbrites= 3;
+
+// toggle the latch so the shiftbrites accept new values
+static void sb_toggle_latch(void)
+{
+ _delay_us(15);
+ PORTC|= (1<<PC1);
+ _delay_us(15);
+ PORTC&= ~(1<<PC1);
+}
+
+// shift out one 32-bit shiftbrite register.
+static void sb_shiftout(uint32_t val)
+{
+ //const unsigned clkdelay= 2;
+ for(int8_t i= 31; i>=0; i--) {
+ //_delay_us(clkdelay);
+ PORTC&= ~(1<<PC0); // clock lo
+ if((val>>i)&1)
+ PORTC|= (1<<PC2); // data bit
+ else
+ PORTC&= ~(1<<PC2);
+ //_delay_us(clkdelay);
+ PORTC|= (1<<PC0); // clock hi
+ }
+}
+
+// shift out all color values to connected shiftbrites
+static void sb_update_all_colors(void)
+{
+ for(int i= sb_num_shiftbrites-1; i>=0; i--)
+ sb_shiftout( (uint32_t)sb_colors[i].g | ((uint32_t)sb_colors[i].r<<10) | ((uint32_t)sb_colors[i].b<<20) );
+ sb_toggle_latch();
+}
+
+
+// set the color of a shiftbrite.
+void sb_setcolor(uint8_t lamp_index, uint8_t r, uint8_t g, uint8_t b)
+{
+ if(lamp_index>=MAXSHIFTBRITES) return;
+ sb_colors[lamp_index].r= r<<2;
+ sb_colors[lamp_index].g= g<<2;
+ sb_colors[lamp_index].b= b<<2;
+ sb_update_all_colors();
+}
+
+
+#if 0
+static void tmp_shiftbritetest(void)
+{
+ sb_shiftout( (uint32_t)(100) | ((uint32_t)(120)<<10) | ((uint32_t)(100)<<20) | ((uint32_t)1<<30) );
+ sb_shiftout( (uint32_t)(100) | ((uint32_t)(120)<<10) | ((uint32_t)(100)<<20) | ((uint32_t)1<<30) );
+ sb_shiftout( (uint32_t)(100) | ((uint32_t)(120)<<10) | ((uint32_t)(100)<<20) | ((uint32_t)1<<30) );
+ _delay_us(15);
+ PORTC|= (1<<PC1);
+ _delay_us(15);
+ PORTC&= ~(1<<PC1);
+ sb_shiftout( (uint32_t)(1023) | ((uint32_t)(0)<<10) | ((uint32_t)(0)<<20) );
+ sb_shiftout( (uint32_t)(0) | ((uint32_t)(1023)<<10) | ((uint32_t)(0)<<20) );
+ sb_shiftout( (uint32_t)(0) | ((uint32_t)(0)<<10) | ((uint32_t)(1023)<<20) );
+ _delay_us(15);
+ PORTC|= (1<<PC1);
+ _delay_us(15);
+ PORTC&= ~(1<<PC1);
+}
+#endif
+
+// write default values to config registers of all shiftbrites
+static void sb_set_default_config_values(void)
+{
+ for(int i= 0; i<sb_num_shiftbrites; i++)
+ sb_shiftout( (uint32_t)(100) | ((uint32_t)(120)<<10) | ((uint32_t)(100)<<20) | ((uint32_t)1<<30) );
+ sb_toggle_latch();
+}
+
+// setup port for shiftbrites
+void sb_init(void)
+{
+ PORTC= 0;
+ DDRC= (1<<PC0) | (1<<PC1) | (1<<PC2);
+ sb_set_default_config_values();
+#if 0
+ for(int k= 0; k<1000; k++)
+ {
+ memset((void*)sb_colors, 0, sizeof(sb_colors));
+ sb_setcolor(k%sb_num_shiftbrites, 0xff, 0x00, 0xff);
+ _delay_ms(100);
+ }
+#endif
+}
+
+
+
+
+
diff --git a/shiftbrite.h b/shiftbrite.h
new file mode 100644
index 0000000..d2f5ebd
--- /dev/null
+++ b/shiftbrite.h
@@ -0,0 +1,5 @@
+// setup port for shiftbrites
+void sb_init(void);
+
+// set the color of a shiftbrite.
+void sb_setcolor(uint8_t lamp_index, uint8_t r, uint8_t g, uint8_t b);