Use native eol, fix messed up files.
authorMalte S. Stretz <mss@apache.org>
Mon, 9 Feb 2009 11:47:58 +0000 (11:47 +0000)
committerMalte S. Stretz <mss@apache.org>
Mon, 9 Feb 2009 11:47:58 +0000 (11:47 +0000)
src/dmx.c
src/main.c
src/mcu.h
src/mcu_config.h
src/pins.h
src/sched.c
src/tlc.c
src/tlc.h

index dd21637..be82313 100644 (file)
--- a/src/dmx.c
+++ b/src/dmx.c
@@ -96,9 +96,9 @@ DT(mark_sync,  mark_wait,  {}, (g_frame_count >= 2), 1);
 DT(data_store, data_store, { g_data = (g_data << 1) | pin_get(PIN_DMX); }, 1);
 state_nop:
 }
-\r
-\r
-void int_dummy(void) { }\r
+
+
+void int_dummy(void) { }
 
 
 void dmx_init(void)
@@ -148,7 +148,7 @@ void dmx_int_disable()
 
 
 #else
-void int_dummy(void) { }\r
+void int_dummy(void) { }
 
 
 void dmx_init(void)
index 18fa1b0..63559fa 100644 (file)
@@ -1,65 +1,65 @@
-// http://www.nongnu.org/avr-libc/user-manual/modules.html\r
-\r
-#include "mcu.h"\r
-\r
-#include "sched.h"\r
-#include "dmx.h"\r
-#include "tlc.h"\r
-#include "sd.h"\r
-\r
-#include "buffer.h"\r
-\r
-\r
-// http://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html\r
-#if __GNUC__ < 4\r
-#error GCC 4.x.x required!\r
-#endif\r
-\r
-//////////////////////////////////////////\r
-// Interrupts\r
-\r
-// INT0:  External int, DMX sync\r
-mcu_isr(INT0);\r
-\r
-// TIMER0:  8-Bit: 4 us for DMX, timeouts\r
-mcu_isr(TIMER0_OVF);\r
-\r
-// TIMER1: 16-Bit: GSCLK\r
-mcu_isr(TIMER1_COMPA);\r
-// TIMER2:  8-Bit: GS-Refresh-Timer\r
-mcu_isr(TIMER2_COMP);\r
-\r
-\r
-//////////////////////////////////////////\r
-\r
-int main(void)\r
-{\r
-  cli();\r
-  mcu_init();\r
-\r
-  // Initialize scheduler.\r
-  sched_init();\r
-\r
-  // Initialize buffer.\r
-  buffer_init();\r
-\r
-  // Initialize peripherals.\r
-  //sd_init();\r
-  //dmx_init();\r
-  tlc_init();\r
-\r
-  sei();\r
-  // Start DMX\r
-  //dmx_start();\r
-  // not done yet, use dummy data\r
-  //buffer_next();\r
-\r
-  // Start scheduler.\r
-  //sched_loop();\r
-\r
-  while (1) {\r
-    buffer_next();\r
-    tlc_wait_for_data();\r
-  }\r
-  return 0;\r
-}\r
+// http://www.nongnu.org/avr-libc/user-manual/modules.html
+
+#include "mcu.h"
+
+#include "sched.h"
+#include "dmx.h"
+#include "tlc.h"
+#include "sd.h"
+
+#include "buffer.h"
+
+
+// http://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
+#if __GNUC__ < 4
+#error GCC 4.x.x required!
+#endif
+
+//////////////////////////////////////////
+// Interrupts
+
+// INT0:  External int, DMX sync
+mcu_isr(INT0);
+
+// TIMER0:  8-Bit: 4 us for DMX, timeouts
+mcu_isr(TIMER0_OVF);
+
+// TIMER1: 16-Bit: GSCLK
+mcu_isr(TIMER1_COMPA);
+// TIMER2:  8-Bit: GS-Refresh-Timer
+mcu_isr(TIMER2_COMP);
+
+
+//////////////////////////////////////////
+
+int main(void)
+{
+  cli();
+  mcu_init();
+
+  // Initialize scheduler.
+  sched_init();
+
+  // Initialize buffer.
+  buffer_init();
+
+  // Initialize peripherals.
+  //sd_init();
+  //dmx_init();
+  tlc_init();
+
+  sei();
+  // Start DMX
+  //dmx_start();
+  // not done yet, use dummy data
+  //buffer_next();
+
+  // Start scheduler.
+  //sched_loop();
+
+  while (1) {
+    buffer_next();
+    tlc_wait_for_data();
+  }
+  return 0;
+}
index 3f8d29c..826ef51 100644 (file)
--- a/src/mcu.h
+++ b/src/mcu.h
@@ -7,8 +7,8 @@
 
 #include "pins.h"
 
-#include "mcu_config.h"\r
-\r
+#include "mcu_config.h"
+
 #define nop() asm volatile ("nop")
 
 #define mcu_isr(name) ISR(name ## _vect) { INT_ ## name (); } int main(void)
 #else
 #error Unknown MCU
 #endif
-\r
-\r
-\r
-#define mcu_init() pin_out(PIN_DEBUG)\r
-volatile uint8_t gg_mcu_debug;\r
-#define mcu_debug_apply() do { if (gg_mcu_debug) { pin_on(PIN_DEBUG); } else { pin_off(PIN_DEBUG); } } while (0)\r
-#define mcu_debug()       do { gg_mcu_debug = ~gg_mcu_debug; mcu_debug_apply(); } while (0)\r
-#define mcu_debug_on()    do { gg_mcu_debug =             1; mcu_debug_apply(); } while (0)\r
-#define mcu_debug_off()   do { gg_mcu_debug =             0; mcu_debug_apply(); } while (0)\r
+
+
+
+#define mcu_init() pin_out(PIN_DEBUG)
+volatile uint8_t gg_mcu_debug;
+#define mcu_debug_apply() do { if (gg_mcu_debug) { pin_on(PIN_DEBUG); } else { pin_off(PIN_DEBUG); } } while (0)
+#define mcu_debug()       do { gg_mcu_debug = ~gg_mcu_debug; mcu_debug_apply(); } while (0)
+#define mcu_debug_on()    do { gg_mcu_debug =             1; mcu_debug_apply(); } while (0)
+#define mcu_debug_off()   do { gg_mcu_debug =             0; mcu_debug_apply(); } while (0)
index b503c01..a84b9f2 100644 (file)
@@ -1,19 +1,19 @@
-#pragma once\r
-\r
-#define PIN_TLC_GSCK  PIN_15\r
-#define PIN_TLC_SCLK  PIN_28\r
-#define PIN_TLC_XLAT  PIN_27\r
-#define PIN_TLC_SIN   PIN_26\r
-#define PIN_TLC_BLNK  PIN_25\r
-#define PIN_TLC_VPRG  PIN_24\r
-\r
-#define PIN_DMX   PIN_INT0\r
-#define DMX_VECT  INT0_vect\r
-\r
-#define INT_TIMER1_COMPA tlc_int_timer1_ocma\r
-#define INT_TIMER2_COMP  tlc_int_timer2_ocm\r
-\r
-#define INT_TIMER0_OVF   dmx_int_timer0_ovf\r
-#define INT_INT0         dmx_int_ext\r
-\r
-#define PIN_DEBUG     PIN_14\r
+#pragma once
+
+#define PIN_TLC_GSCK  PIN_15
+#define PIN_TLC_SCLK  PIN_28
+#define PIN_TLC_XLAT  PIN_27
+#define PIN_TLC_SIN   PIN_26
+#define PIN_TLC_BLNK  PIN_25
+#define PIN_TLC_VPRG  PIN_24
+
+#define PIN_DMX   PIN_INT0
+#define DMX_VECT  INT0_vect
+
+#define INT_TIMER1_COMPA tlc_int_timer1_ocma
+#define INT_TIMER2_COMP  tlc_int_timer2_ocm
+
+#define INT_TIMER0_OVF   dmx_int_timer0_ovf
+#define INT_INT0         dmx_int_ext
+
+#define PIN_DEBUG     PIN_14
index 2f55b81..6fa953a 100644 (file)
@@ -1,32 +1,32 @@
-#pragma once\r
-\r
-#include <avr/io.h>\r
-\r
-#include "bits.h"\r
-\r
-//////////////////////////////////////////\r
-\r
-#define pin_is_set(pp)  (bit_is_set(pin_SFR_PIN(pp), pin_PIN_NUM(pp)))\r
-#define pin_get(pp)     (pin_is_set(pp) >> pin_PIN_NUM(pp))\r
-\r
-#define pin_on(pp)      bits_mask_on( pin_SFR_PRT(pp), pin_PIN_VAL(pp))\r
-#define pin_off(pp)     bits_mask_off(pin_SFR_PRT(pp), pin_PIN_VAL(pp))\r
-\r
-#define pin_in(pp)      bits_mask_off(pin_SFR_DDR(pp), pin_PIN_VAL(pp))\r
-#define pin_out(pp)     bits_mask_on( pin_SFR_DDR(pp), pin_PIN_VAL(pp))\r
-\r
-//////////////////////////////////////////\r
-\r
-#define pin_pin(pp)  pin_PIN_NUM(pp)\r
-#define pin_inr(pp)  pin_SFR_PIN(pp)\r
-#define pin_outr(pp) pin_SFR_PRT(pp)\r
-#define pin_ddr(pp)  pin_SFR_DDR(pp)\r
-\r
-//////////////////////////////////////////\r
-\r
-#define pin_PIN_NUM(port, pin) pin\r
-#define pin_PIN_VAL(port, pin) bits_value(pin)\r
-#define pin_SFR_PIN(port, pin) PIN  ## port\r
-#define pin_SFR_PRT(port, pin) PORT ## port\r
-#define pin_SFR_DDR(port, pin) DDR  ## port\r
-\r
+#pragma once
+
+#include <avr/io.h>
+
+#include "bits.h"
+
+//////////////////////////////////////////
+
+#define pin_is_set(pp)  (bit_is_set(pin_SFR_PIN(pp), pin_PIN_NUM(pp)))
+#define pin_get(pp)     (pin_is_set(pp) >> pin_PIN_NUM(pp))
+
+#define pin_on(pp)      bits_mask_on( pin_SFR_PRT(pp), pin_PIN_VAL(pp))
+#define pin_off(pp)     bits_mask_off(pin_SFR_PRT(pp), pin_PIN_VAL(pp))
+
+#define pin_in(pp)      bits_mask_off(pin_SFR_DDR(pp), pin_PIN_VAL(pp))
+#define pin_out(pp)     bits_mask_on( pin_SFR_DDR(pp), pin_PIN_VAL(pp))
+
+//////////////////////////////////////////
+
+#define pin_pin(pp)  pin_PIN_NUM(pp)
+#define pin_inr(pp)  pin_SFR_PIN(pp)
+#define pin_outr(pp) pin_SFR_PRT(pp)
+#define pin_ddr(pp)  pin_SFR_DDR(pp)
+
+//////////////////////////////////////////
+
+#define pin_PIN_NUM(port, pin) pin
+#define pin_PIN_VAL(port, pin) bits_value(pin)
+#define pin_SFR_PIN(port, pin) PIN  ## port
+#define pin_SFR_PRT(port, pin) PORT ## port
+#define pin_SFR_DDR(port, pin) DDR  ## port
+
index 26ef1ca..0d6378f 100644 (file)
@@ -52,7 +52,7 @@ void sched_loop()
   sched_func_t first;
   uint8_t      running;
   sched_func_t func;
-  sched_res_t  resched;\r
+  sched_res_t  resched;
   
   while (1) {
     // Be atomic.
@@ -78,10 +78,10 @@ void sched_loop()
         sched_put(func);
       
       // Get next pointer, exit loop if done.
-      running  = sched_get(&func);\r
-      if (func == first) {\r
-        sched_put(func);\r
-        running = 0;\r
+      running  = sched_get(&func);
+      if (func == first) {
+        sched_put(func);
+        running = 0;
       }
     }
 
index 29cbbc1..345c945 100644 (file)
--- a/src/tlc.c
+++ b/src/tlc.c
-#include <avr/io.h>\r
-\r
-#include "tlc.h"\r
-\r
-#include "mcu.h"\r
-#include "pins.h"\r
-\r
-#include "sched.h"\r
-#include "buffer.h"\r
-\r
-/////////////////////////////////////////\r
-\r
-sched_res_t wait_for_data(void);\r
-\r
-volatile uint8_t g_data_available;\r
-\r
-/////////////////////////////////////////\r
-\r
-volatile uint8_t g_data_shifting;\r
-void send_data(void);\r
-void start_gscycle(void);\r
-void tlc_wait_for_data()\r
-{\r
-  if (g_data_shifting) return;\r
-  send_data();\r
-  start_gscycle();\r
-  // Continue in background...\r
-}\r
-void set_shifting_off(void)\r
-{\r
-  //sched_put(&wait_for_data);\r
-  g_data_shifting = 0;\r
-  mcu_debug_off();\r
-}\r
-\r
-/////////////////////////////////////////\r
-\r
-// XLAT pulse to apply data to internal register.\r
-void clock_xlat(void)\r
-{\r
-  pin_on(PIN_TLC_XLAT);\r
-  pin_off(PIN_TLC_XLAT);\r
-}\r
-\r
-// SCLK pulse to clock in serial data from SIN.\r
-void clock_sclk(void)\r
-{\r
-  pin_on(PIN_TLC_SCLK);\r
-  pin_off(PIN_TLC_SCLK);\r
-}\r
-\r
-void set_blnk_on(void)\r
-{\r
-  pin_on(PIN_TLC_BLNK);\r
-}\r
-\r
-void set_blnk_off(void)\r
-{\r
-  pin_off(PIN_TLC_BLNK);\r
-}\r
-\r
-void set_vprg_gs_mode(void)\r
-{\r
-  pin_off(PIN_TLC_VPRG);\r
-}\r
-\r
-void set_vprg_dc_mode(void)\r
-{\r
-  pin_on(PIN_TLC_VPRG);\r
-}\r
-\r
-/////////////////////////////////////////\r
-\r
-void tlc_init(void)\r
-{\r
-  // Initialize blanked (ie. LEDs off).\r
-  pin_out(PIN_TLC_BLNK);\r
-  pin_on( PIN_TLC_BLNK);\r
-\r
-  // Timer 1 is for our GSCLK:  We refresh with a GS cycle of\r
-  // about 100 Hz (cf. Timer 2), for each full cycle we need to\r
-  // clock the PWM 4096 times.\r
-  // We need about 38 clocks to get 4096 cycles at 100 Hz.\r
-  mcu_set_timer1_ic(38);\r
-  // 50% duty cycle.\r
-  mcu_set_timer1_ocma(1);\r
-  // * CS1 = 0001:  No prescaler. (p100)\r
-  // * WGM1 = 1110: Fast PWM, TOP at ICR1\r
-  // * COM1A = 10: Set at 0, clear at Output Compare Match)\r
-  TCCR1B = bits_value(CS10) | bits_value(WGM13) | bits_value(WGM12);\r
-  TCCR1A = bits_value(WGM11) | bits_value(COM1A1);\r
-\r
-  /* Timer 2: Refresh-Timer */\r
-  // * AS2 = 0: Use IO-clock (16 MHz) for base frequency (p119)\r
-  // * Mode: Normal mode, no PWM, count upwards (WGM21:0 = 00) (p117)\r
-  // * Disable Output on OC2, needed for SPI (COM21:0 = 00) (p117)\r
-  // * Prescaler: 1024 (CS22:0 = 111) => 15625 Hz\r
-  TCCR2 = bits_value(CS22) | bits_value(CS21) | bits_value(CS20);\r
-  // To get a 100 Hz clock we need to count 157 times (~ 99.5 Hz).\r
-  mcu_set_timer2_ocm(156);\r
-\r
-  // All these pins write to the painter.\r
-  pin_out(PIN_TLC_GSCK);\r
-  pin_out(PIN_TLC_VPRG);\r
-  pin_out(PIN_TLC_XLAT);\r
-  pin_out(PIN_TLC_SCLK);\r
-  pin_out(PIN_TLC_SIN);\r
-\r
-  // Wait for first DMX packet.\r
-}\r
-\r
-void tlc_set_data_done(void)\r
-{\r
-  g_data_available = 1;\r
-}\r
-\r
-/////////////////////////////////////////\r
-\r
-void start_gscycle(void)\r
-{\r
-  g_data_shifting = 1;\r
-  // Start counter with next GS pulse.\r
-  mcu_int_timer1_ocma_enable();\r
-}\r
-\r
-void tlc_int_timer1_ocma(void)\r
-{\r
-  // First, disable this interrupt.\r
-  mcu_int_timer1_ocma_disable();\r
-\r
-  // Restart and enable timeout timer.\r
-  mcu_set_timer2_cnt(0);\r
-  mcu_int_timer2_ocm_enable();\r
-  mcu_debug_on();\r
-\r
-  // Switch off BLNK.\r
-  set_blnk_off();\r
-  // Hack: Switch on GSCLK\r
-  pin_out(PIN_TLC_GSCK);\r
-}\r
-\r
-void tlc_int_timer2_ocm(void)\r
-{\r
-  // Hack: Switch off GSCLK\r
-  pin_in(PIN_TLC_GSCK);\r
-  // Go into BLNK mode (switch off LEDs and reset GSCLK counter)\r
-  set_blnk_on();\r
-\r
-  // Disable GS cycle timeout timer.\r
-  mcu_int_timer2_ocm_disable();\r
-\r
-  // Wait for next DMX packet.\r
-  set_shifting_off();\r
-}\r
-\r
-/////////////////////////////////////////\r
-\r
-void shift8(uint8_t byte)\r
-{\r
-  // Shift out all eight bits.\r
-  for (uint8_t bit = bits_uint8(1, 0, 0, 0, 0, 0, 0, 0); bit; bit >>= 1) {\r
-    if (byte & bit) {\r
-      pin_on(PIN_TLC_SIN);\r
-    } else {\r
-      pin_off(PIN_TLC_SIN);\r
-    }\r
-    clock_sclk();\r
-  }\r
-}\r
-\r
-void shift12(uint8_t byte)\r
-{\r
-  // The data in the upper 8 bits.\r
-  shift8(byte);\r
-\r
-  // Plus 4 zero bits (makes a shift by 4).\r
-  pin_off(PIN_TLC_SIN);\r
-  for (uint8_t bit = 4; bit; bit--) {\r
-    clock_sclk();\r
-  }\r
-}\r
-\r
-/////////////////////////////////////////\r
-\r
-void send_gs_data(void)\r
-{\r
-  // Set VPRG to GS mode.\r
-  set_vprg_gs_mode();\r
-  // Because the TLCs are daisy-chained, we have to shift out the RGB data\r
-  // starting at the end.  Each painter has 3 TLCs (with 16 channels each), \r
-  // for the colors red, green, blue.  So we've got to shift out the 16 blue\r
-  // channels of the last TLC first, then 16 green ones and finally 16 red \r
-  // ones.  The last data we shift out is thus the first red of the first\r
-  // painter.\r
-  // This will always point to the start of the current painter data, \r
-  // starting with the last one.\r
-  char * painter_gs = gg_buffer_gs\r
-                    + TLC_N_CHANNELS\r
-                    - TLC_N_CHANNELS_PER_PAINTER;\r
-  // Find the current data byte to shift out, starting with the last one.\r
-  // Its signed so we can determine when we reached the end/start, eight\r
-  // bit are enough to index 48 channels per painter.\r
-#if TLC_N_CHANNELS_PER_PAINTER != 48\r
-#error What a weird painter...\r
-#endif\r
-  while (1) {\r
-    int8_t index = TLC_N_CHANNELS_PER_PAINTER - 1;\r
-    while (1) {\r
-      // Shift out current channel.\r
-      shift12(painter_gs[index]);\r
-\r
-      // Skip two colors.\r
-      index -= 3;\r
-\r
-      // If we reached the start, we jump to the next color.\r
-      if (index < 0) {\r
-        // Did we just finish the last (ie. red) channel?\r
-        if (index == -3)\r
-          break;\r
-\r
-        // Jump to end again and skip to next color.\r
-        index += TLC_N_CHANNELS_PER_PAINTER - 1;\r
-      }\r
-    }\r
-\r
-    // Did we just finish the last (ie. first) painter?\r
-    if (painter_gs == gg_buffer_gs)\r
-      break;\r
-\r
-    // Move to next painter.\r
-    painter_gs -= TLC_N_CHANNELS_PER_PAINTER;\r
-  }\r
-}\r
-\r
-void send_dc_data(void)\r
-{\r
-  // Set VPRG to DC mode. \r
-  set_vprg_dc_mode();  \r
-\r
-  // All TLCs on all the connected painters will get the same DC value.\r
-  // That makes it easy to generate the 6-Bit format we need:  We just\r
-  // create a constant buffer for the packed rgb values, containing four\r
-  // values for each color.\r
-  uint8_t dc_out[3][3];\r
-  for (int8_t rgb = 2; rgb >= 0; rgb--) {\r
-    uint8_t dc_data = gg_buffer_dc[rgb] & bits_uint8(1, 1, 1, 1, 1, 1, 0, 0);\r
-    dc_out[rgb][2] = (dc_data << 0) | (dc_data >> 6);\r
-    dc_out[rgb][1] = (dc_data << 2) | (dc_data >> 4);\r
-    dc_out[rgb][0] = (dc_data << 4) | (dc_data >> 2);\r
-  }\r
-\r
-  // Now, shift out the dc-data like we do it with the gs-data:  First the\r
-  // last blue, then green and red of the last painter, until we reach the\r
-  // first red.\r
-  int8_t painter = N_PAINTER;\r
-  do {\r
-    int8_t rgb = 3 - 1;\r
-    do {\r
-      int8_t index = (TLC_N_CHANNELS_PER_TLC / 4) * 3 - 1;\r
-      do {\r
-        shift8(dc_out[rgb][index % 3]);\r
-        index--;\r
-      } while (index != -1);\r
-      rgb--;\r
-    } while (rgb != -1);\r
-    painter--;\r
-  } while (painter != 0);\r
-}\r
-\r
-void send_data(void)\r
-{\r
-  // Always shift out DC first.\r
-  send_dc_data();\r
-  clock_xlat();\r
-\r
-  // No extra SCLK needed, just shift out all GS data.\r
-  send_gs_data();\r
-  clock_xlat();\r
-\r
-  clock_sclk();\r
-\r
-  g_data_available = 0;\r
-}\r
-\r
-\r
-/////////////////////////////////////////\r
-\r
-sched_res_t wait_for_data(void)\r
-{\r
-  if (!g_data_available) return SCHED_RE;\r
-\r
-  send_data();\r
-  start_gscycle();\r
-  // Continue in background...\r
-\r
-  // TODO: next data\r
-  //buffer_next();\r
-\r
-  return SCHED_OK;\r
-}\r
-\r
-/////////////////////////////////////////\r
+#include <avr/io.h>
+
+#include "tlc.h"
+
+#include "mcu.h"
+#include "pins.h"
+
+#include "sched.h"
+#include "buffer.h"
+
+/////////////////////////////////////////
+
+sched_res_t wait_for_data(void);
+
+volatile uint8_t g_data_available;
+
+/////////////////////////////////////////
+
+volatile uint8_t g_data_shifting;
+void send_data(void);
+void start_gscycle(void);
+void tlc_wait_for_data()
+{
+  if (g_data_shifting) return;
+  send_data();
+  start_gscycle();
+  // Continue in background...
+}
+void set_shifting_off(void)
+{
+  //sched_put(&wait_for_data);
+  g_data_shifting = 0;
+  mcu_debug_off();
+}
+
+/////////////////////////////////////////
+
+// XLAT pulse to apply data to internal register.
+void clock_xlat(void)
+{
+  pin_on(PIN_TLC_XLAT);
+  pin_off(PIN_TLC_XLAT);
+}
+
+// SCLK pulse to clock in serial data from SIN.
+void clock_sclk(void)
+{
+  pin_on(PIN_TLC_SCLK);
+  pin_off(PIN_TLC_SCLK);
+}
+
+void set_blnk_on(void)
+{
+  pin_on(PIN_TLC_BLNK);
+}
+
+void set_blnk_off(void)
+{
+  pin_off(PIN_TLC_BLNK);
+}
+
+void set_vprg_gs_mode(void)
+{
+  pin_off(PIN_TLC_VPRG);
+}
+
+void set_vprg_dc_mode(void)
+{
+  pin_on(PIN_TLC_VPRG);
+}
+
+/////////////////////////////////////////
+
+void tlc_init(void)
+{
+  // Initialize blanked (ie. LEDs off).
+  pin_out(PIN_TLC_BLNK);
+  pin_on( PIN_TLC_BLNK);
+
+  // Timer 1 is for our GSCLK:  We refresh with a GS cycle of
+  // about 100 Hz (cf. Timer 2), for each full cycle we need to
+  // clock the PWM 4096 times.
+  // We need about 38 clocks to get 4096 cycles at 100 Hz.
+  mcu_set_timer1_ic(38);
+  // 50% duty cycle.
+  mcu_set_timer1_ocma(1);
+  // * CS1 = 0001:  No prescaler. (p100)
+  // * WGM1 = 1110: Fast PWM, TOP at ICR1
+  // * COM1A = 10: Set at 0, clear at Output Compare Match)
+  TCCR1B = bits_value(CS10) | bits_value(WGM13) | bits_value(WGM12);
+  TCCR1A = bits_value(WGM11) | bits_value(COM1A1);
+
+  /* Timer 2: Refresh-Timer */
+  // * AS2 = 0: Use IO-clock (16 MHz) for base frequency (p119)
+  // * Mode: Normal mode, no PWM, count upwards (WGM21:0 = 00) (p117)
+  // * Disable Output on OC2, needed for SPI (COM21:0 = 00) (p117)
+  // * Prescaler: 1024 (CS22:0 = 111) => 15625 Hz
+  TCCR2 = bits_value(CS22) | bits_value(CS21) | bits_value(CS20);
+  // To get a 100 Hz clock we need to count 157 times (~ 99.5 Hz).
+  mcu_set_timer2_ocm(156);
+
+  // All these pins write to the painter.
+  pin_out(PIN_TLC_GSCK);
+  pin_out(PIN_TLC_VPRG);
+  pin_out(PIN_TLC_XLAT);
+  pin_out(PIN_TLC_SCLK);
+  pin_out(PIN_TLC_SIN);
+
+  // Wait for first DMX packet.
+}
+
+void tlc_set_data_done(void)
+{
+  g_data_available = 1;
+}
+
+/////////////////////////////////////////
+
+void start_gscycle(void)
+{
+  g_data_shifting = 1;
+  // Start counter with next GS pulse.
+  mcu_int_timer1_ocma_enable();
+}
+
+void tlc_int_timer1_ocma(void)
+{
+  // First, disable this interrupt.
+  mcu_int_timer1_ocma_disable();
+
+  // Restart and enable timeout timer.
+  mcu_set_timer2_cnt(0);
+  mcu_int_timer2_ocm_enable();
+  mcu_debug_on();
+
+  // Switch off BLNK.
+  set_blnk_off();
+  // Hack: Switch on GSCLK
+  pin_out(PIN_TLC_GSCK);
+}
+
+void tlc_int_timer2_ocm(void)
+{
+  // Hack: Switch off GSCLK
+  pin_in(PIN_TLC_GSCK);
+  // Go into BLNK mode (switch off LEDs and reset GSCLK counter)
+  set_blnk_on();
+
+  // Disable GS cycle timeout timer.
+  mcu_int_timer2_ocm_disable();
+
+  // Wait for next DMX packet.
+  set_shifting_off();
+}
+
+/////////////////////////////////////////
+
+void shift8(uint8_t byte)
+{
+  // Shift out all eight bits.
+  for (uint8_t bit = bits_uint8(1, 0, 0, 0, 0, 0, 0, 0); bit; bit >>= 1) {
+    if (byte & bit) {
+      pin_on(PIN_TLC_SIN);
+    } else {
+      pin_off(PIN_TLC_SIN);
+    }
+    clock_sclk();
+  }
+}
+
+void shift12(uint8_t byte)
+{
+  // The data in the upper 8 bits.
+  shift8(byte);
+
+  // Plus 4 zero bits (makes a shift by 4).
+  pin_off(PIN_TLC_SIN);
+  for (uint8_t bit = 4; bit; bit--) {
+    clock_sclk();
+  }
+}
+
+/////////////////////////////////////////
+
+void send_gs_data(void)
+{
+  // Set VPRG to GS mode.
+  set_vprg_gs_mode();
+  // Because the TLCs are daisy-chained, we have to shift out the RGB data
+  // starting at the end.  Each painter has 3 TLCs (with 16 channels each), 
+  // for the colors red, green, blue.  So we've got to shift out the 16 blue
+  // channels of the last TLC first, then 16 green ones and finally 16 red 
+  // ones.  The last data we shift out is thus the first red of the first
+  // painter.
+  // This will always point to the start of the current painter data, 
+  // starting with the last one.
+  char * painter_gs = gg_buffer_gs
+                    + TLC_N_CHANNELS
+                    - TLC_N_CHANNELS_PER_PAINTER;
+  // Find the current data byte to shift out, starting with the last one.
+  // Its signed so we can determine when we reached the end/start, eight
+  // bit are enough to index 48 channels per painter.
+#if TLC_N_CHANNELS_PER_PAINTER != 48
+#error What a weird painter...
+#endif
+  while (1) {
+    int8_t index = TLC_N_CHANNELS_PER_PAINTER - 1;
+    while (1) {
+      // Shift out current channel.
+      shift12(painter_gs[index]);
+
+      // Skip two colors.
+      index -= 3;
+
+      // If we reached the start, we jump to the next color.
+      if (index < 0) {
+        // Did we just finish the last (ie. red) channel?
+        if (index == -3)
+          break;
+
+        // Jump to end again and skip to next color.
+        index += TLC_N_CHANNELS_PER_PAINTER - 1;
+      }
+    }
+
+    // Did we just finish the last (ie. first) painter?
+    if (painter_gs == gg_buffer_gs)
+      break;
+
+    // Move to next painter.
+    painter_gs -= TLC_N_CHANNELS_PER_PAINTER;
+  }
+}
+
+void send_dc_data(void)
+{
+  // Set VPRG to DC mode. 
+  set_vprg_dc_mode();  
+
+  // All TLCs on all the connected painters will get the same DC value.
+  // That makes it easy to generate the 6-Bit format we need:  We just
+  // create a constant buffer for the packed rgb values, containing four
+  // values for each color.
+  uint8_t dc_out[3][3];
+  for (int8_t rgb = 2; rgb >= 0; rgb--) {
+    uint8_t dc_data = gg_buffer_dc[rgb] & bits_uint8(1, 1, 1, 1, 1, 1, 0, 0);
+    dc_out[rgb][2] = (dc_data << 0) | (dc_data >> 6);
+    dc_out[rgb][1] = (dc_data << 2) | (dc_data >> 4);
+    dc_out[rgb][0] = (dc_data << 4) | (dc_data >> 2);
+  }
+
+  // Now, shift out the dc-data like we do it with the gs-data:  First the
+  // last blue, then green and red of the last painter, until we reach the
+  // first red.
+  int8_t painter = N_PAINTER;
+  do {
+    int8_t rgb = 3 - 1;
+    do {
+      int8_t index = (TLC_N_CHANNELS_PER_TLC / 4) * 3 - 1;
+      do {
+        shift8(dc_out[rgb][index % 3]);
+        index--;
+      } while (index != -1);
+      rgb--;
+    } while (rgb != -1);
+    painter--;
+  } while (painter != 0);
+}
+
+void send_data(void)
+{
+  // Always shift out DC first.
+  send_dc_data();
+  clock_xlat();
+
+  // No extra SCLK needed, just shift out all GS data.
+  send_gs_data();
+  clock_xlat();
+
+  clock_sclk();
+
+  g_data_available = 0;
+}
+
+
+/////////////////////////////////////////
+
+sched_res_t wait_for_data(void)
+{
+  if (!g_data_available) return SCHED_RE;
+
+  send_data();
+  start_gscycle();
+  // Continue in background...
+
+  // TODO: next data
+  //buffer_next();
+
+  return SCHED_OK;
+}
+
+/////////////////////////////////////////
index 24314f1..596a778 100644 (file)
--- a/src/tlc.h
+++ b/src/tlc.h
@@ -1,20 +1,20 @@
-#pragma once\r
-\r
-#include "config.h"\r
-\r
-#define TLC_N_CHANNELS_PER_TLC 16\r
-#define TLC_N_TLCS_PER_PAINTER  3\r
-\r
-#define TLC_N_CHANNELS_PER_PAINTER (TLC_N_TLCS_PER_PAINTER * TLC_N_CHANNELS_PER_TLC)\r
-\r
-#define TLC_N_CHANNELS (N_PAINTER * TLC_N_CHANNELS_PER_PAINTER)\r
-\r
-void tlc_init(void);\r
-//void tlc_start(void);\r
-\r
-void tlc_set_data_done(void);\r
-\r
-void tlc_wait_for_data(void);\r
-\r
-void tlc_int_timer1_ocma(void);\r
-void tlc_int_timer2_ocm(void);\r
+#pragma once
+
+#include "config.h"
+
+#define TLC_N_CHANNELS_PER_TLC 16
+#define TLC_N_TLCS_PER_PAINTER  3
+
+#define TLC_N_CHANNELS_PER_PAINTER (TLC_N_TLCS_PER_PAINTER * TLC_N_CHANNELS_PER_TLC)
+
+#define TLC_N_CHANNELS (N_PAINTER * TLC_N_CHANNELS_PER_PAINTER)
+
+void tlc_init(void);
+//void tlc_start(void);
+
+void tlc_set_data_done(void);
+
+void tlc_wait_for_data(void);
+
+void tlc_int_timer1_ocma(void);
+void tlc_int_timer2_ocm(void);