Browse Source

added first draft of current meassuring software

stefan 1 year ago
parent
commit
3c68ef353f
6 changed files with 495 additions and 0 deletions
  1. 1 0
      .gitignore
  2. 26 0
      software/Makefile
  3. 63 0
      software/inc/light_ws2812.h
  4. 21 0
      software/inc/ws2812_config.h
  5. 170 0
      software/src/light_ws2812.c
  6. 214 0
      software/src/main.c

+ 1 - 0
.gitignore

@@ -1 +1,2 @@
 wardrobeLedController/wardrobeLedController-backups
+*.elf

+ 26 - 0
software/Makefile

@@ -0,0 +1,26 @@
+DEVICE		:= atmega32
+SRC			:= src/light_ws2812.c src/main.c
+TARGET		:= wardrobeLedController.elf
+INCLUDE		:= -I inc
+F_CPU		:= 16000000
+
+AVRDUDE		:= avrdude
+PROGRAMMER	:= avrispmkII
+
+CC			:= avr-gcc
+
+diag:
+	echo $(ASM_SRC)
+	echo $(ASMFLAGS)
+
+all: $(TARGET)
+
+
+$(TARGET): Makefile $(SRC)
+	$(CC) $(INCLUDE) -mmcu=$(DEVICE) -O3 -D F_CPU=$(F_CPU) $(SRC) -o $@
+
+flash: all
+	$(AVRDUDE) -c $(PROGRAMMER) -p $(DEVICE) -U flash:w:$(TARGET):e
+
+fuse:
+	$(AVRDUDE) -c $(PROGRAMMER) -p $(DEVICE) -U lfuse:w:0xff:m -U hfuse:w:0xd9:m

+ 63 - 0
software/inc/light_ws2812.h

@@ -0,0 +1,63 @@
+/*
+ * light weight WS2812 lib include
+ *
+ * Version 2.0a3  - Jan 18th 2014
+ * Author: Tim (cpldcpu@gmail.com) 
+ *
+ * Please do not change this file! All configuration is handled in "ws2812_config.h"
+ *
+ * License: GNU GPL v2 (see License.txt)
+ +
+ */ 
+
+#ifndef LIGHT_WS2812_H_
+#define LIGHT_WS2812_H_
+
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include "ws2812_config.h"
+
+/*
+ *  Structure of the LED array
+ */
+
+struct cRGB { uint8_t g; uint8_t r; uint8_t b; };
+
+/* User Interface
+ * 
+ * Input:
+ *         ledarray:           An array of GRB data describing the LED colors
+ *         number_of_leds:     The number of LEDs to write
+ *         pinmask (optional): Bitmask describing the output bin. e.g. _BV(PB0)
+ *
+ * The functions will perform the following actions:
+ *         - Set the data-out pin as output
+ *         - Send out the LED data 
+ *         - Wait 50�s to reset the LEDs
+ */
+
+void ws2812_setleds    (struct cRGB *ledarray, uint16_t number_of_leds);
+void ws2812_setleds_pin(struct cRGB *ledarray, uint16_t number_of_leds,uint8_t pinmask);
+
+/* 
+ * Old interface / Internal functions
+ *
+ * The functions take a byte-array and send to the data output as WS2812 bitstream.
+ * The length is the number of bytes to send - three per LED.
+ */
+
+void ws2812_sendarray     (uint8_t *array,uint16_t length);
+void ws2812_sendarray_mask(uint8_t *array,uint16_t length, uint8_t pinmask);
+
+
+/*
+ * Internal defines
+ */
+
+#define CONCAT(a, b)            a ## b
+#define CONCAT_EXP(a, b)   CONCAT(a, b)
+
+#define ws2812_PORTREG  CONCAT_EXP(PORT,ws2812_port)
+#define ws2812_DDRREG   CONCAT_EXP(DDR,ws2812_port)
+
+#endif /* LIGHT_WS2812_H_ */

+ 21 - 0
software/inc/ws2812_config.h

@@ -0,0 +1,21 @@
+/*
+ * light_ws2812_config.h
+ *
+ * Created: 18.01.2014 09:58:15
+ *
+ * User Configuration file for the light_ws2812_lib
+ *
+ */ 
+
+
+#ifndef WS2812_CONFIG_H_
+#define WS2812_CONFIG_H_
+
+///////////////////////////////////////////////////////////////////////
+// Define I/O pin
+///////////////////////////////////////////////////////////////////////
+
+#define ws2812_port D     // Data port 
+#define ws2812_pin  4     // Data out pin
+
+#endif /* WS2812_CONFIG_H_ */

+ 170 - 0
software/src/light_ws2812.c

@@ -0,0 +1,170 @@
+/*
+* light weight WS2812 lib V2.0b
+*
+* Controls WS2811/WS2812/WS2812B RGB-LEDs
+* Author: Tim (cpldcpu@gmail.com)
+*
+* Jan 18th, 2014  v2.0b Initial Version
+*
+* License: GNU GPL v2 (see License.txt)
+*/
+
+#include "light_ws2812.h"
+#include <avr/interrupt.h>
+#include <avr/io.h>
+#include <util/delay.h>
+ 
+void inline ws2812_setleds(struct cRGB *ledarray, uint16_t leds)
+{
+   ws2812_setleds_pin(ledarray,leds, _BV(ws2812_pin));
+}
+
+void inline ws2812_setleds_pin(struct cRGB *ledarray, uint16_t leds, uint8_t pinmask)
+{
+  ws2812_DDRREG |= pinmask; // Enable DDR
+  ws2812_sendarray_mask((uint8_t*)ledarray,leds+leds+leds,pinmask);
+  _delay_us(50);
+}
+
+void ws2812_sendarray(uint8_t *data,uint16_t datlen)
+{
+  ws2812_sendarray_mask(data,datlen,_BV(ws2812_pin));
+}
+
+/*
+  This routine writes an array of bytes with RGB values to the Dataout pin
+  using the fast 800kHz clockless WS2811/2812 protocol.
+*/
+
+// Timing in ns
+#define w_zeropulse   350
+#define w_onepulse    900
+#define w_totalperiod 1250
+
+// Fixed cycles used by the inner loop
+#define w_fixedlow    2
+#define w_fixedhigh   4
+#define w_fixedtotal  8   
+
+// Insert NOPs to match the timing, if possible
+#define w_zerocycles    (((F_CPU/1000)*w_zeropulse          )/1000000)
+#define w_onecycles     (((F_CPU/1000)*w_onepulse    +500000)/1000000)
+#define w_totalcycles   (((F_CPU/1000)*w_totalperiod +500000)/1000000)
+
+// w1 - nops between rising edge and falling edge - low
+#define w1 (w_zerocycles-w_fixedlow)
+// w2   nops between fe low and fe high
+#define w2 (w_onecycles-w_fixedhigh-w1)
+// w3   nops to complete loop
+#define w3 (w_totalcycles-w_fixedtotal-w1-w2)
+
+#if w1>0
+  #define w1_nops w1
+#else
+  #define w1_nops  0
+#endif
+
+// The only critical timing parameter is the minimum pulse length of the "0"
+// Warn or throw error if this timing can not be met with current F_CPU settings.
+#define w_lowtime ((w1_nops+w_fixedlow)*1000000)/(F_CPU/1000)
+#if w_lowtime>550
+   #error "Light_ws2812: Sorry, the clock speed is too low. Did you set F_CPU correctly?"
+#elif w_lowtime>450
+   #warning "Light_ws2812: The timing is critical and may only work on WS2812B, not on WS2812(S)."
+   #warning "Please consider a higher clockspeed, if possible"
+#endif   
+
+#if w2>0
+#define w2_nops w2
+#else
+#define w2_nops  0
+#endif
+
+#if w3>0
+#define w3_nops w3
+#else
+#define w3_nops  0
+#endif
+
+#define w_nop1  "nop      \n\t"
+#define w_nop2  "rjmp .+0 \n\t"
+#define w_nop4  w_nop2 w_nop2
+#define w_nop8  w_nop4 w_nop4
+#define w_nop16 w_nop8 w_nop8
+
+void inline ws2812_sendarray_mask(uint8_t *data,uint16_t datlen,uint8_t maskhi)
+{
+  uint8_t curbyte,ctr,masklo;
+  uint8_t sreg_prev;
+  
+  masklo	=~maskhi&ws2812_PORTREG;
+  maskhi |=        ws2812_PORTREG;
+  sreg_prev=SREG;
+  cli();  
+
+  while (datlen--) {
+    curbyte=*data++;
+    
+    asm volatile(
+    "       ldi   %0,8  \n\t"
+    "loop%=:            \n\t"
+    "       out   %2,%3 \n\t"    //  '1' [01] '0' [01] - re
+#if (w1_nops&1)
+w_nop1
+#endif
+#if (w1_nops&2)
+w_nop2
+#endif
+#if (w1_nops&4)
+w_nop4
+#endif
+#if (w1_nops&8)
+w_nop8
+#endif
+#if (w1_nops&16)
+w_nop16
+#endif
+    "       sbrs  %1,7  \n\t"    //  '1' [03] '0' [02]
+    "       out   %2,%4 \n\t"    //  '1' [--] '0' [03] - fe-low
+    "       lsl   %1    \n\t"    //  '1' [04] '0' [04]
+#if (w2_nops&1)
+  w_nop1
+#endif
+#if (w2_nops&2)
+  w_nop2
+#endif
+#if (w2_nops&4)
+  w_nop4
+#endif
+#if (w2_nops&8)
+  w_nop8
+#endif
+#if (w2_nops&16)
+  w_nop16 
+#endif
+    "       out   %2,%4 \n\t"    //  '1' [+1] '0' [+1] - fe-high
+#if (w3_nops&1)
+w_nop1
+#endif
+#if (w3_nops&2)
+w_nop2
+#endif
+#if (w3_nops&4)
+w_nop4
+#endif
+#if (w3_nops&8)
+w_nop8
+#endif
+#if (w3_nops&16)
+w_nop16
+#endif
+
+    "       dec   %0    \n\t"    //  '1' [+2] '0' [+2]
+    "       brne  loop%=\n\t"    //  '1' [+3] '0' [+4]
+    :	"=&d" (ctr)
+    :	"r" (curbyte), "I" (_SFR_IO_ADDR(ws2812_PORTREG)), "r" (maskhi), "r" (masklo)
+    );
+  }
+  
+  SREG=sreg_prev;
+}

+ 214 - 0
software/src/main.c

@@ -0,0 +1,214 @@
+
+#include <string.h>
+#include "light_ws2812.h"
+#include <avr/io.h>
+
+#define LED_NUM_WIDTH 39u
+#define LED_NUM_HEIGTH 12u
+#define ADC_MEAN_SAMPLES 32u
+
+struct cRGB ledState[102];
+const struct cRGB ledStateDefault[102] =
+{
+    {4u, 4u, 255u},
+    {6u, 6u, 255u},
+    {8u, 8u, 255u},
+    {11u, 11u, 255u},
+    {14u, 14u, 250u},
+    {17u, 17u, 240u},
+    {20u, 20u, 230u},
+    {25u, 25u, 220u},
+    {30u, 30u, 210u},
+    {35u, 35u, 200u},
+    {40u, 40u, 190u},
+    {45u, 35u, 180u},
+    {50u, 50u, 170u},
+    {55u, 55u, 160u},
+    {60u, 60u, 150u},
+    {65u, 65u, 140u},
+    {70u, 70u, 130u},
+    {80u, 80u, 120u},
+    {90u, 90u, 110u},
+    {100u, 100u, 100u},
+    {90u, 90u, 110u},
+    {80u, 80u, 120u},
+    {70u, 70u, 130u},
+    {65u, 65u, 140u},
+    {60u, 60u, 150u},
+    {55u, 55u, 160u},
+    {50u, 50u, 170u},
+    {45u, 45u, 180u},
+    {40u, 40u, 190u},
+    {35u, 35u, 200u},
+    {30u, 30u, 210u},
+    {25u, 25u, 220u},
+    {20u, 20u, 230u},
+    {17u, 17u, 240u},
+    {14u, 14u, 250u},
+    {11u, 11u, 255u},
+    {8u, 8u, 255u},
+    {6u, 6u, 255u},
+    {4u, 4u, 255u},
+
+    {4u, 4u, 255u},
+    {4u, 8u, 200},
+    {4u, 15u, 150u},
+    {4u, 20u, 100u},
+    {4u, 60u, 70u},
+    {4u, 100u, 50u},
+    {4u, 100u, 50u},
+    {4u, 60u, 70u},
+    {4u, 20u, 100u},
+    {4u, 15u, 150u},
+    {4u, 8u, 200u},
+    {4u, 4u, 255u},
+
+    {4u, 4u, 255u},
+    {6u, 6u, 255u},
+    {8u, 8u, 255u},
+    {11u, 11u, 255u},
+    {14u, 14u, 250u},
+    {17u, 17u, 240u},
+    {20u, 20u, 230u},
+    {25u, 25u, 220u},
+    {30u, 30u, 210u},
+    {35u, 35u, 200u},
+    {40u, 40u, 190u},
+    {45u, 35u, 180u},
+    {50u, 50u, 170u},
+    {55u, 55u, 160u},
+    {60u, 60u, 150u},
+    {65u, 65u, 140u},
+    {70u, 70u, 130u},
+    {80u, 80u, 120u},
+    {90u, 90u, 110u},
+    {100u, 100u, 100u},
+    {90u, 90u, 110u},
+    {80u, 80u, 120u},
+    {70u, 70u, 130u},
+    {65u, 65u, 140u},
+    {60u, 60u, 150u},
+    {55u, 55u, 160u},
+    {50u, 50u, 170u},
+    {45u, 45u, 180u},
+    {40u, 40u, 190u},
+    {35u, 35u, 200u},
+    {30u, 30u, 210u},
+    {25u, 25u, 220u},
+    {20u, 20u, 230u},
+    {17u, 17u, 240u},
+    {14u, 14u, 250u},
+    {11u, 11u, 255u},
+    {8u, 8u, 255u},
+    {6u, 6u, 255u},
+    {4u, 4u, 255u},
+
+    {4u, 4u, 255u},
+    {4u, 8u, 200},
+    {4u, 15u, 150u},
+    {4u, 20u, 100u},
+    {4u, 60u, 70u},
+    {4u, 100u, 50u},
+    {4u, 100u, 50u},
+    {4u, 60u, 70u},
+    {4u, 20u, 100u},
+    {4u, 15u, 150u},
+    {4u, 8u, 200u},
+    {4u, 4u, 255u},
+};
+
+const int8_t currentSteps[LED_NUM_HEIGTH] = {
+    7,
+    10,
+    15,
+    25,
+    35,
+    40,
+    48,
+    55,
+    65,
+    80,
+    100,
+    120,
+};
+
+int main(void)
+{
+    int32_t adc_result_ch1 = 0u;
+    int32_t adc_result_ch2 = 0u;
+    uint8_t led_num;
+    DDRA = (uint8_t)0x00u;
+    ADCSRA = (uint8_t)0b10000111u;
+
+    while(1)
+    {
+        adc_result_ch1 = 0;
+        adc_result_ch2 = 0;
+        for(uint32_t i = 0u; i < ADC_MEAN_SAMPLES; i ++)
+        {
+            // reading ch1
+            ADCSRA |= (1<<ADSC);
+            ADMUX = (uint8_t)0b010001001;
+            while((ADCSRA&(1<<ADIF))==0);
+            // ignore negative values
+            if((ADCH & 0x02u) == 0u)
+            {
+                adc_result_ch1 += ((int16_t)ADCL + ((int16_t)ADCH << 8u)) >> 2u;
+            }
+            // reading ch2
+            ADCSRA |= (1<<ADSC);
+            ADMUX = (uint8_t)0b010001101;
+            while((ADCSRA&(1<<ADIF))==0);
+            if((ADCH & 0x02u) == 0u)
+            {
+                adc_result_ch2 += ((int16_t)ADCL + ((int16_t)ADCH << 8u)) >> 2u;
+            }
+        }
+        adc_result_ch1 = adc_result_ch1 / ADC_MEAN_SAMPLES;
+        adc_result_ch2 = adc_result_ch2 / ADC_MEAN_SAMPLES;
+
+        // copy the default
+        (void)memcpy(ledState, ledStateDefault, sizeof(ledState));
+
+        // ch1 left
+        for(uint32_t i = 0u; i < LED_NUM_HEIGTH; i ++)
+        {
+            led_num = LED_NUM_HEIGTH + LED_NUM_WIDTH - 1 - i;
+
+            if (adc_result_ch1 >= currentSteps[i])
+            {
+                ledState[led_num].g = 0;
+                ledState[led_num].b = 0;
+                ledState[led_num].r = 255;
+            }
+            else if (i > 0 && adc_result_ch1 >= currentSteps[i - 1])
+            {
+                ledState[led_num].g = 0;
+                ledState[led_num].b = 0;
+                ledState[led_num].r = adc_result_ch1 - currentSteps[i - 1];
+            }
+        }
+
+        // ch2 right
+        for(uint32_t i = 0u; i < LED_NUM_HEIGTH; i ++)
+        {
+            led_num = LED_NUM_HEIGTH + (2 * LED_NUM_WIDTH) + i;
+
+            if (adc_result_ch2 >= currentSteps[i])
+            {
+                ledState[led_num].g = 0;
+                ledState[led_num].b = 0;
+                ledState[led_num].r = 255;
+            }
+            else if (i > 0 && adc_result_ch2 >= currentSteps[i - 1])
+            {
+                ledState[led_num].g = 0;
+                ledState[led_num].b = 0;
+                ledState[led_num].r = adc_result_ch2 - currentSteps[i - 1];
+            }
+        }
+
+        ws2812_setleds(ledState, 102);
+    }
+    return 0;
+}