Permalink
Browse files

Add a scrolling message function

  • Loading branch information...
1 parent 88938c5 commit ab158f909df365b69777b7237cd82f0305e274ac @jwhite66 committed with Jeremy White Sep 23, 2011
Showing with 246 additions and 11 deletions.
  1. +2 −0 .gitignore
  2. +10 −3 Makefile
  3. +0 −3 TODO
  4. +2 −0 drive.c
  5. +4 −0 elegante.license.txt
  6. BIN elegante_pixel.ttf
  7. +8 −5 led.h
  8. +89 −0 led.pde
  9. +131 −0 makemap.c
View
2 .gitignore
@@ -3,4 +3,6 @@ arduino-0022
*.elf
*.hex
drive
+makemap
+message.h
generated_led.cpp
View
13 Makefile
@@ -48,15 +48,23 @@ LDFLAGS = -mmcu=$(MCU) -lm -Wl,--gc-sections -Os
OBJECTS=generated_led.o Print.o HardwareSerial.o wiring.o main.o
-all: $(TARGET_HEX) drive
+all: $(TARGET_HEX) drive makemap
+
+message.h: Makefile makemap
+ ./makemap elegante_pixel.ttf "HELLO WORLD." > message.h
generated_led.cpp: led.pde led.h
@echo '#include <WProgram.h>' > $@
@cat $< >>$@
+generated_led.o: led.pde led.h message.h
+
drive: drive.c led.h
gcc -Wall -o $@ $<
+makemap: makemap.c led.h
+ gcc -Wall -o $@ -I /usr/include/freetype2 $< -lfreetype -lm
+
led.elf: $(OBJECTS)
$(CC) $(LDFLAGS) -o $@ $(OBJECTS)
@@ -67,7 +75,6 @@ Print.o: $(ARDUINO_CORE_PATH)/Print.cpp
HardwareSerial.o: $(ARDUINO_CORE_PATH)/HardwareSerial.cpp
wiring.o: $(ARDUINO_CORE_PATH)/wiring.c
main.o: $(ARDUINO_CORE_PATH)/main.cpp
-led.o: led.cpp
upload: reset raw_upload
@@ -87,4 +94,4 @@ reset:
$$STTYF $(ARD_PORT) -hupcl
clean:
- $(RM) $(OBJECTS) $(TARGET_HEX) led.elf generated_led.cpp drive
+ $(RM) $(OBJECTS) $(TARGET_HEX) led.elf generated_led.cpp drive makemap message.h
View
3 TODO
@@ -1,8 +1,5 @@
* Set up licensing (GPL v3)
* Provide a flash ram setting to perform init on boot
-* Provide a command to store a compressed pattern into flash ram
-* Provide a setting to play a compressed pattern
- - Optionally on boot
--- Long Term ---
View
2 drive.c
@@ -381,6 +381,8 @@ int main(int argc, char *argv[])
perform_cmd(fd, COMMAND_STATUS);
else if (strcmp(argv[i], "chase") == 0)
perform_cmd(fd, COMMAND_CHASE);
+ else if (strcmp(argv[i], "display") == 0)
+ perform_cmd(fd, COMMAND_SCROLL_DISPLAY);
else if (strcmp(argv[i],"bulb") == 0)
write_bulbs = 1;
else if (perform_custom(fd, argv[i]) != 0)
View
4 elegante.license.txt
@@ -0,0 +1,4 @@
+The FontStruction “elegante pixel”
+(http://fontstruct.com/fontstructions/show/243993) by “oneup” is licensed
+under a Creative Commons Attribution Share Alike license
+(http://creativecommons.org/licenses/by-sa/3.0/).
View
BIN elegante_pixel.ttf
Binary file not shown.
View
13 led.h
@@ -50,8 +50,11 @@
/*----------------------------------------------------------------------------
** Command list
**--------------------------------------------------------------------------*/
-#define COMMAND_ACK (BULB_FLAG_COMMAND | 1)
-#define COMMAND_INIT (BULB_FLAG_COMMAND | 2)
-#define COMMAND_STATUS (BULB_FLAG_COMMAND | 3)
-#define COMMAND_CLEAR (BULB_FLAG_COMMAND | 4)
-#define COMMAND_CHASE (BULB_FLAG_COMMAND | 5)
+#define COMMAND_ACK (BULB_FLAG_COMMAND | 1)
+#define COMMAND_INIT (BULB_FLAG_COMMAND | 2)
+#define COMMAND_STATUS (BULB_FLAG_COMMAND | 3)
+#define COMMAND_CLEAR (BULB_FLAG_COMMAND | 4)
+#define COMMAND_CHASE (BULB_FLAG_COMMAND | 5)
+#define COMMAND_SCROLL_DISPLAY (BULB_FLAG_COMMAND | 6)
+
+
View
89 led.pde
@@ -11,6 +11,7 @@
**
**--------------------------------------------------------------------------*/
#include "led.h"
+#include "message.h"
/*----------------------------------------------------------------------------
@@ -295,6 +296,80 @@ void process_bulb(const uint8_t *data)
}
}
+/*----------------------------------------------------------------------------
+** Message scrolling code
+**--------------------------------------------------------------------------*/
+#define SCROLL_INTERVAL 250
+uint8_t *g_scroll_pos = g_message_bits;
+int g_scroll_width = 5;
+unsigned long g_next_scroll = 0;
+
+uint8_t g_scrolling = 0;
+
+void scroll_display(void)
+{
+ int i;
+ uint8_t *p;
+ bulb pixel;
+ int x, y;
+ int shift;
+
+ p = g_scroll_pos;
+ for (x = 0; x < g_scroll_width; x++)
+ {
+ for (y = 0; y < MESSAGE_ROWS; y++)
+ {
+ int addr;
+ if (y % 2 == 0)
+ {
+ shift = 1 << y;
+ addr = (x * MESSAGE_ROWS) + y;
+ }
+ else
+ {
+ shift = 1 << (MESSAGE_ROWS - y - 1);
+ addr = (x * MESSAGE_ROWS) + (MESSAGE_ROWS - y) - 1;
+ }
+
+ if (*p & shift)
+ pixel.bright = MAX_BRIGHT;
+ else
+ pixel.bright = 0;
+
+ pixel.stringmask = _BV(0);
+ pixel.addrshift = addr << 2;
+ pixel.redshift = 0xf0;
+ pixel.greenshift = 0;
+ pixel.blueshift = 0;
+
+ write_raw_bulbs(1, &pixel);
+ }
+
+ if (((++p) - g_message_bits) >= sizeof(g_message_bits))
+ p = g_message_bits;
+
+ }
+}
+
+void scroll_advance(int howmuch)
+{
+ while (howmuch-- > 0)
+ if ((++g_scroll_pos) - g_message_bits >= sizeof(g_message_bits))
+ g_scroll_pos = g_message_bits;
+}
+
+void check_scroll()
+{
+ unsigned long now = millis();
+
+ if (now >= g_next_scroll || now <= SCROLL_INTERVAL)
+ {
+ g_next_scroll = now + SCROLL_INTERVAL;
+ scroll_advance(1);
+ scroll_display();
+ }
+
+}
/*----------------------------------------------------------------------------
** init
@@ -391,6 +466,17 @@ void process_command(const uint8_t *data)
chase();
break;
+ case COMMAND_SCROLL_DISPLAY:
+ g_scrolling = ! g_scrolling;
+ if (g_scrolling)
+ {
+ scroll_display();
+ g_next_scroll = millis() + SCROLL_INTERVAL;
+ }
+ else
+ init(0);
+ break;
+
default:
Serial.print("Unknown command: ");
Serial.println((int) BULB_FLAG_ADDRESS(data));
@@ -420,6 +506,9 @@ void loop()
{
uint8_t data[4];
+ if (g_scrolling)
+ check_scroll();
+
/*------------------------------------------------------------------------
** Pull a command from the serial port, and execute it
**----------------------------------------------------------------------*/
View
131 makemap.c
@@ -0,0 +1,131 @@
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <assert.h>
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+void draw_bitmap(FT_Bitmap* bitmap, char **comments, char *bits)
+{
+ int x, y;
+
+ for (x = 0; x < bitmap->width; x++)
+ for (y = 0; y < bitmap->rows; y++)
+ if (bitmap->buffer[y * bitmap->width + x])
+ {
+ bits[x] |= (1 << (bitmap->rows - y - 1));
+ comments[y][x] = 'X';
+ }
+
+}
+
+
+int
+main( int argc,
+ char** argv )
+{
+ FT_Library library;
+ FT_Face face;
+
+ FT_Error error;
+
+ char* filename;
+ char* text;
+
+ int n, num_chars;
+
+ char comments[20][2048];
+ char bits[2048];
+ int rows = 0;
+
+ int x, y;
+
+ char *commentp[20];
+ char *bitp;
+
+ if ( argc != 3 )
+ {
+ fprintf ( stderr, "usage: %s font sample-text\n", argv[0] );
+ exit( 1 );
+ }
+
+ filename = argv[1]; /* first argument */
+ text = argv[2]; /* second argument */
+ num_chars = strlen( text );
+
+ error = FT_Init_FreeType( &library ); /* initialize library */
+ /* error handling omitted */
+
+ error = FT_New_Face( library, argv[1], 0, &face ); /* create face object */
+ /* error handling omitted */
+
+#ifdef NOCLUE
+printf("fixed sizes%d\n", face->num_fixed_sizes);
+printf("units_per_EM %d\n", face->units_per_EM);
+printf("height %d\n", face->height);
+printf("ascender %d\n", face->ascender);
+printf("descender %d\n", face->descender);
+printf("max advance width %d\n", face->max_advance_width);
+printf("max advance height %d\n", face->max_advance_height);
+printf("bbox.xMin %ld, xMax %ld\n", face->bbox.xMin, face->bbox.xMax);
+printf("bbox.yMin %ld, yMax %ld\n", face->bbox.yMin, face->bbox.yMax);
+printf("size.metrics.x_ppem %d\n", face->size->metrics.x_ppem);
+printf("size.metrics.x_scale %ld\n", face->size->metrics.x_scale);
+printf("size.metrics.y_ppem %d\n", face->size->metrics.y_ppem);
+printf("size.metrics.y_scale %ld\n", face->size->metrics.y_scale);
+printf("size.metrics.height %ld\n", face->size->metrics.height);
+#endif
+
+/* 1024 works for the 5x7 font. Go figure */
+ error = FT_Set_Char_Size( face, 512, 0, 72, 0 ); /* set character size */
+
+ memset(comments, ' ', sizeof(comments));
+ memset(bits, 0, sizeof(bits));
+
+ for ( n = 0, x= 0; n < num_chars; n++ )
+ {
+ /* load glyph image into the slot (erase previous one) */
+ error = FT_Load_Char( face, text[n], FT_LOAD_RENDER);
+ if ( error )
+ continue; /* ignore errors */
+
+//printf("%d: max %d, current %d\n", n, rows, face->glyph->bitmap.rows);
+ if (n > 0)
+ assert(rows >= face->glyph->bitmap.rows);
+ else
+ rows = face->glyph->bitmap.rows;
+
+ assert(x + face->glyph->bitmap.width < sizeof(bits));
+ for (y = 0; y < rows; y++)
+ {
+ commentp[y] = comments[y] + x;
+ }
+ bitp = bits + x;
+
+ draw_bitmap(&face->glyph->bitmap, commentp, bitp);
+
+ x += face->glyph->bitmap.width;
+
+ /* Deliberately add 1 column of spaces */
+ x++;
+ }
+
+ printf("#define MESSAGE_ROWS %d\n", rows);
+ printf("unsigned char g_message_bits[] = { ");
+ for (n = 0; n < x; n++)
+ printf("0x%02x%c", (int) bits[n], n == x - 1 ? ' ' : ',');
+ printf("};\n");
+ for (y = 0; y < rows; y++)
+ {
+ comments[y][x] = 0;
+ printf("//%s\n", comments[y]);
+ }
+
+ FT_Done_Face ( face );
+ FT_Done_FreeType( library );
+
+ return 0;
+}
+
+/* EOF */

0 comments on commit ab158f9

Please sign in to comment.