Compare commits
	
		
			No commits in common. "master" and "feature/bootloader" have entirely different histories.
		
	
	
		
			master
			...
			feature/bo
		
	
		
							
								
								
									
										3
									
								
								firmware/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								firmware/.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -1,3 +0,0 @@ | |||||||
| *.o |  | ||||||
| *.bin |  | ||||||
| *.hex |  | ||||||
| @ -1,21 +0,0 @@ | |||||||
| MCU=atmega8 |  | ||||||
| CFLAGS=-g -Wall --param=min-pagesize=0 -mcall-prologues -mmcu=$(MCU) -O2 -DF_CPU=16000000 |  | ||||||
| LDFLAGS=-Wl,-gc-sections -Wl,-relax |  | ||||||
| CC=avr-gcc |  | ||||||
| TARGET=leddie-firmware |  | ||||||
| OBJECT_FILES=lib/light_ws2812.o lib/pm.o lib/mma8653.o lib/timers.o lib/button.o lib/system.o app.o |  | ||||||
| 
 |  | ||||||
| all: $(TARGET).hex |  | ||||||
| 
 |  | ||||||
| clean: |  | ||||||
| 	rm -f *.o *.hex *.obj *.hex |  | ||||||
| 	rm -f lib/*.o |  | ||||||
| 
 |  | ||||||
| %.hex: %.obj |  | ||||||
| 	avr-objcopy -R .eeprom -O ihex $< $@ |  | ||||||
| 
 |  | ||||||
| %.obj: $(OBJECT_FILES) |  | ||||||
| 	$(CC) $(CFLAGS) $(OBJECT_FILES) $(LDFLAGS) -o $@ |  | ||||||
| 
 |  | ||||||
| program: $(TARGET).hex |  | ||||||
| 	avrdude -p $(MCU) -c usbasp  -U flash:w:$(TARGET).hex |  | ||||||
							
								
								
									
										174
									
								
								firmware/app.c
									
									
									
									
									
								
							
							
						
						
									
										174
									
								
								firmware/app.c
									
									
									
									
									
								
							| @ -1,174 +0,0 @@ | |||||||
| #include "lib/system.h" |  | ||||||
| #include "lib/hal.h" |  | ||||||
| #include <stdlib.h> |  | ||||||
| #include <util/delay.h> |  | ||||||
| 
 |  | ||||||
| #define TIMER_INMENU TIMER_APP0 |  | ||||||
| #define TIMER_AUX TIMER_APP1 |  | ||||||
| 
 |  | ||||||
| static int clr = 1; |  | ||||||
| 
 |  | ||||||
| void axl_test() |  | ||||||
| { |  | ||||||
| 	int ret; |  | ||||||
| 	struct axl_result measurements; |  | ||||||
| 	 |  | ||||||
| 	int dir_x; |  | ||||||
| 	int dir_y; |  | ||||||
| 	int ledno; |  | ||||||
| 	int intens; |  | ||||||
| 
 |  | ||||||
| 	if (block_for(TIMER_AUX, timer_ms(50))) { |  | ||||||
| 		display_clear(0); |  | ||||||
| 		 |  | ||||||
| 		#define THRES 10 |  | ||||||
| 		ret = mma8653_get_measurements(&measurements); |  | ||||||
| 		dir_x = 0; |  | ||||||
| 		if (measurements.x > THRES) |  | ||||||
| 			dir_x = -1; |  | ||||||
| 		else if (measurements.x < -THRES) |  | ||||||
| 			dir_x = 1; |  | ||||||
| 		dir_y = 0; |  | ||||||
| 		if (measurements.y > THRES) |  | ||||||
| 			dir_y = 1; |  | ||||||
| 		else if (measurements.y < -THRES) |  | ||||||
| 			dir_y = -1; |  | ||||||
| 
 |  | ||||||
| 		if (dir_y == -1) |  | ||||||
| 			ledno = dir_x + 1; |  | ||||||
| 		else if (dir_y == 0) |  | ||||||
| 			ledno = 3 + 1 -dir_x; |  | ||||||
| 		else if (dir_y == 1) |  | ||||||
| 			ledno = dir_x + 6 + 1; |  | ||||||
| 		 |  | ||||||
| 		intens = abs(measurements.x + measurements.y); |  | ||||||
| 		intens = intens >> 2; |  | ||||||
| 		if (intens < 1) |  | ||||||
| 			intens = 1; |  | ||||||
| 		if (measurements.z > 0) |  | ||||||
| 			led[ledno].b = intens; |  | ||||||
| 		else |  | ||||||
| 			led[ledno].r = intens; |  | ||||||
| 
 |  | ||||||
| 		if (ret) |  | ||||||
| 			led[ret].r = 0x10; |  | ||||||
| 
 |  | ||||||
| 		display_update(); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| void led_test(int first_launch) |  | ||||||
| { |  | ||||||
| 	static int i; |  | ||||||
| 	 |  | ||||||
| 	if (first_launch) { |  | ||||||
| 		i = 0; |  | ||||||
| 		led[0].r = 1; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (block_for(TIMER_AUX, timer_ms(30))) { |  | ||||||
| 		led[i].g = 0x0; |  | ||||||
| 		i = (i + 1) % STRIPLEN; |  | ||||||
| 		led[i].g = 0x10; |  | ||||||
| 		if (led[i].r && led[i].b) { |  | ||||||
| 			led[i].r = 0; |  | ||||||
| 			led[i].b = 1; |  | ||||||
| 		} else if (led[i].r) { |  | ||||||
| 			led[i].b = 1; |  | ||||||
| 		} else { |  | ||||||
| 			led[i].r = 1; |  | ||||||
| 			led[i].b = 0; |  | ||||||
| 		} |  | ||||||
| 		display_update(); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void system_test() |  | ||||||
| { |  | ||||||
| 	// Display power states on first face
 |  | ||||||
| 	if (HAL_ASSERTED_N(VLED_EN_N)) |  | ||||||
| 		led[0].b = 1; |  | ||||||
| 	else |  | ||||||
| 		led[0].b = 0; |  | ||||||
| 
 |  | ||||||
| 	if (HAL_ASSERTED_N(CHG_ACTIVE_N)) |  | ||||||
| 		led[1].r = 1; |  | ||||||
| 	else |  | ||||||
| 		led[1].r = 0; |  | ||||||
| 	 |  | ||||||
| 	if (block_for(TIMER_AUX, timer_ms(50))) |  | ||||||
| 		display_update(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Note: This is only for watchdog testing.
 |  | ||||||
| // Never use _delay_ms(...) in your programs. Use timer_* functions instead.
 |  | ||||||
| void wdt_test() |  | ||||||
| { |  | ||||||
| 	int i = 50; |  | ||||||
| 	display_clear(0); |  | ||||||
| 	while (i--) { |  | ||||||
| 		led[0].b = !led[0].b; |  | ||||||
| 		display_update(); |  | ||||||
| 		_delay_ms(100); |  | ||||||
| 	} |  | ||||||
| 	led[0].b = 0; |  | ||||||
| 	led[0].r = 1; |  | ||||||
| 	display_update(); |  | ||||||
| 	_delay_ms(2000); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void app_init() |  | ||||||
| { |  | ||||||
| 	clr = 1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void app_suspend() |  | ||||||
| { |  | ||||||
| 	return; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #define APP_COUNT 4 |  | ||||||
| enum app_return app_mainloop() |  | ||||||
| { |  | ||||||
| 	static int app_sel = 0; |  | ||||||
| 
 |  | ||||||
| 	if (button_event(EV_PRESS)) { |  | ||||||
| 		app_sel = (app_sel + 1) % APP_COUNT; |  | ||||||
| 		display_clear(); |  | ||||||
| 		for (int i = 0; i < STRIPLEN; i += 9) { |  | ||||||
| 			led[app_sel + i].g = 4; |  | ||||||
| 		} |  | ||||||
| 		display_update(); |  | ||||||
| 		timer_set(TIMER_INMENU, timer_ms(750)); |  | ||||||
| 		clr = 1; |  | ||||||
| 	} else if (button_event(EV_LONGPRESS)) { |  | ||||||
| 		return SUSPEND; |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	if (timer_expired(TIMER_INMENU)) { |  | ||||||
| 		if (clr) { |  | ||||||
| 			display_clear(); |  | ||||||
| 		} |  | ||||||
| 		switch (app_sel) { |  | ||||||
| 			case 0: |  | ||||||
| 				led_test(clr); |  | ||||||
| 				break; |  | ||||||
| 			case 1: |  | ||||||
| 				axl_test(); |  | ||||||
| 				break; |  | ||||||
| 			case 2: |  | ||||||
| 				system_test(); |  | ||||||
| 				break; |  | ||||||
| 			case 3: |  | ||||||
| 				wdt_test(); |  | ||||||
| 				break; |  | ||||||
| 			default: |  | ||||||
| 				app_sel = 0; |  | ||||||
| 				break; |  | ||||||
| 		} |  | ||||||
| 		clr = 0; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return RUN; |  | ||||||
| } |  | ||||||
| @ -1,9 +0,0 @@ | |||||||
| #!/bin/bash |  | ||||||
| 
 |  | ||||||
| while [ 1 ]; do |  | ||||||
| 	make program |  | ||||||
| 	if [ $? -eq 0 ]; then |  | ||||||
| 		break; |  | ||||||
| 	fi |  | ||||||
| 	sleep 1 |  | ||||||
| done |  | ||||||
| @ -1,87 +0,0 @@ | |||||||
| #include <avr/interrupt.h> |  | ||||||
| #include "button.h" |  | ||||||
| #include "timers.h" |  | ||||||
| #include "hal.h" |  | ||||||
| #include <util/delay.h> |  | ||||||
| 
 |  | ||||||
| #include "pm.h" // TODO: FOR DEBUGGING ONLY |  | ||||||
| 
 |  | ||||||
| volatile enum BUTTON_EVENTS button_event_status = NONE; |  | ||||||
| 
 |  | ||||||
| // User button interrupt
 |  | ||||||
| ISR(INT1_vect) |  | ||||||
| { |  | ||||||
| 	_delay_ms(50); |  | ||||||
| 	if (HAL_ASSERTED_N(BUTTON_N)) { // Button down event
 |  | ||||||
| 		switch (button_event_status) { |  | ||||||
| 			case NONE: // Start processing button from NONE,
 |  | ||||||
| 			case EV_BOOT: // or drop boot event if not polled for,
 |  | ||||||
| 			case EV_PRESS: // or drop current keypress to prevent unhandled keypresses from blocking other would-be-handled keypresses
 |  | ||||||
| 			case EV_DOUBLEPRESS: |  | ||||||
| 			case EV_LONGPRESS: |  | ||||||
| 			case EV_DOUBLELONGPRESS: |  | ||||||
| 				button_event_status = WAIT_FOR_RELEASE_1; |  | ||||||
| 				timer_set(TIMER_BUTTON, timer_ms(500)); |  | ||||||
| 				break; |  | ||||||
| 			case WAIT_FOR_SECOND: |  | ||||||
| 				button_event_status = WAIT_FOR_RELEASE_2; |  | ||||||
| 				timer_set(TIMER_BUTTON, timer_ms(500)); |  | ||||||
| 				break; |  | ||||||
| 			default: |  | ||||||
| 				break; |  | ||||||
| 		} |  | ||||||
| 	} else { // Button up event
 |  | ||||||
| 		switch (button_event_status) { |  | ||||||
| 			case WAIT_FOR_RELEASE_1: |  | ||||||
| 				button_event_status = WAIT_FOR_SECOND; |  | ||||||
| 				break; |  | ||||||
| 			case WAIT_FOR_RELEASE_2: |  | ||||||
| 				button_event_status = EV_DOUBLEPRESS; |  | ||||||
| 				break; |  | ||||||
| 			default: |  | ||||||
| 				break; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void button_init() |  | ||||||
| { |  | ||||||
| 	HAL_INIT(BUTTON_N, INPUT, ON); // Pull-up for user button
 |  | ||||||
| 	button_event_status = EV_BOOT; |  | ||||||
| 
 |  | ||||||
| 	MCUCR = (1 << ISC10); // Any-edge interrupt
 |  | ||||||
| 	GICR = (1 << INT1); // Turn on button interrupt
 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void button_systick_cb() |  | ||||||
| { |  | ||||||
| 	if (button_event_status != 0) { // TODO: we should not enter on pending EV?
 |  | ||||||
| 		if (timer_expired(TIMER_BUTTON)) { |  | ||||||
| 			switch (button_event_status) { |  | ||||||
| 				case WAIT_FOR_RELEASE_1: |  | ||||||
| 					button_event_status = EV_LONGPRESS; |  | ||||||
| 					break; |  | ||||||
| 				case WAIT_FOR_RELEASE_2: |  | ||||||
| 					button_event_status = EV_DOUBLELONGPRESS; |  | ||||||
| 					pm_reset(); // TODO: For debugging purposes only
 |  | ||||||
| 					break; |  | ||||||
| 				case WAIT_FOR_SECOND: |  | ||||||
| 					button_event_status = EV_PRESS; |  | ||||||
| 					break; |  | ||||||
| 				default: |  | ||||||
| 					break; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int button_event(enum BUTTON_EVENTS ev) |  | ||||||
| { |  | ||||||
| 	if (button_event_status == ev) { |  | ||||||
| 		button_event_status = NONE; // Mark as handled
 |  | ||||||
| 		return 1; |  | ||||||
| 	} |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| @ -1,14 +0,0 @@ | |||||||
| #ifndef _BUTTON_H |  | ||||||
| #define _BUTTON_H |  | ||||||
| 
 |  | ||||||
| enum BUTTON_EVENTS { |  | ||||||
| 	NONE, WAIT_FOR_RELEASE_1, WAIT_FOR_SECOND, WAIT_FOR_RELEASE_2, // Intermediate states
 |  | ||||||
| 	EV_PRESS, EV_DOUBLEPRESS, EV_LONGPRESS, EV_DOUBLELONGPRESS, EV_BOOT// Button events
 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| void button_init(); |  | ||||||
| int button_event(enum BUTTON_EVENTS ev); |  | ||||||
| extern void button_systick_cb(); |  | ||||||
| void button_systick_cb(); |  | ||||||
| 
 |  | ||||||
| #endif // _BUTTON_H
 |  | ||||||
| @ -1,51 +0,0 @@ | |||||||
| #ifndef _HAL_H |  | ||||||
| #define _HAL_H |  | ||||||
| 
 |  | ||||||
| #include <avr/io.h> |  | ||||||
| 
 |  | ||||||
| #define HAL_OUTPUT(name) PORT_##name(DDR) |= PIN_##name |  | ||||||
| #define HAL_INPUT(name) PORT_##name(DDR) &= ~(PIN_##name) |  | ||||||
| #define HAL_SET(name) PORT_##name(PORT) |= PIN_##name |  | ||||||
| #define HAL_CLEAR(name) PORT_##name(PORT) &= ~(PIN_##name) |  | ||||||
| #define HAL_ISHIGH(name) (PORT_##name(PIN) & PIN_##name) |  | ||||||
| 
 |  | ||||||
| #define HAL_ON(name) HAL_SET(name) |  | ||||||
| #define HAL_ON_N(name) HAL_CLEAR(name) |  | ||||||
| #define HAL_OFF(name) HAL_CLEAR(name) |  | ||||||
| #define HAL_OFF_N(name) HAL_SET(name) |  | ||||||
| #define HAL_ASSERTED(name) HAL_ISHIGH(name) |  | ||||||
| #define HAL_ASSERTED_N(name) (!HAL_ISHIGH(name)) |  | ||||||
| 
 |  | ||||||
| #define HAL_INIT(name, type, default) HAL_##default(name); HAL_##type(name) |  | ||||||
| 
 |  | ||||||
| #define PORT_VBUS_SENSE(t) t##B |  | ||||||
| #define PIN_VBUS_SENSE (1 << 2) |  | ||||||
| 
 |  | ||||||
| #define PORT_VLED_EN_N(t) t##D |  | ||||||
| #define PIN_VLED_EN_N (1 << 6) // Hotfix
 |  | ||||||
| 
 |  | ||||||
| #define PORT_CHG_ACTIVE_N(t) t##D |  | ||||||
| #define PIN_CHG_ACTIVE_N (1 << 7) // Hotfix
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| #define PORT_BAT_SENSE(t) t##C |  | ||||||
| #define PIN_BAT_SENSE (1 << 0) |  | ||||||
| 
 |  | ||||||
| #define PORT_BAT_SENSE_EN_N(t) t##C |  | ||||||
| #define PIN_BAT_SENSE_EN_N (1 << 1) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| #define PORT_AXL_EN(t) t##C |  | ||||||
| #define PIN_AXL_EN (3 << 2) |  | ||||||
| 
 |  | ||||||
| #define PORT_AXL_I2C(t) t##C |  | ||||||
| #define PIN_AXL_I2C (3 << 4) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| #define PORT_BUTTON_N(t) t##D |  | ||||||
| #define PIN_BUTTON_N (1 << 3) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| // LED pin defined in `light_ws2812.h`.
 |  | ||||||
| 
 |  | ||||||
| #endif |  | ||||||
| @ -1,194 +0,0 @@ | |||||||
| /*
 |  | ||||||
| * light weight WS2812 lib V2.0b |  | ||||||
| * |  | ||||||
| * Controls WS2811/WS2812/WS2812B RGB-LEDs |  | ||||||
| * Author: Tim (cpldcpu@gmail.com) |  | ||||||
| * |  | ||||||
| * Jan 18th, 2014  v2.0b Initial Version |  | ||||||
| * Nov 29th, 2015  v2.3  Added SK6812RGBW support |  | ||||||
| * |  | ||||||
| * License: GNU GPL v2+ (see License.txt) |  | ||||||
| */ |  | ||||||
| 
 |  | ||||||
| #include "light_ws2812.h" |  | ||||||
| #include <avr/interrupt.h> |  | ||||||
| #include <avr/io.h> |  | ||||||
| #include <util/delay.h> |  | ||||||
| 
 |  | ||||||
| // Normally ws2812_sendarray_mask() runs under disabled-interrupt condition,
 |  | ||||||
| // undefine if you want to accept interrupts in that function.
 |  | ||||||
| #define interrupt_is_disabled |  | ||||||
|   |  | ||||||
| // Setleds for standard RGB 
 |  | ||||||
| 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_sendarray_mask((uint8_t*)ledarray,leds+leds+leds,pinmask); |  | ||||||
|   _delay_us(ws2812_resettime); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Setleds for SK6812RGBW
 |  | ||||||
| void inline ws2812_setleds_rgbw(struct cRGBW *ledarray, uint16_t leds) |  | ||||||
| { |  | ||||||
|   ws2812_sendarray_mask((uint8_t*)ledarray,leds<<2,_BV(ws2812_pin)); |  | ||||||
|   _delay_us(ws2812_resettime); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 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 //300
 |  | ||||||
| #define w_onepulse    800 //600
 |  | ||||||
| #define w_totalperiod 1250 //1100
 |  | ||||||
| 
 |  | ||||||
| // 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    +000000)/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" |  | ||||||
| #ifdef interrupt_is_disabled |  | ||||||
| #define w_nop2  "brid .+0 \n\t" |  | ||||||
| #else |  | ||||||
| #define w_nop2  "brtc .+0 \n\t" |  | ||||||
| #endif |  | ||||||
| #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; |  | ||||||
|    |  | ||||||
|   ws2812_DDRREG |= maskhi; // Enable output
 |  | ||||||
|    |  | ||||||
|   masklo	=~maskhi&ws2812_PORTREG; |  | ||||||
|   maskhi |=        ws2812_PORTREG; |  | ||||||
|    |  | ||||||
|   sreg_prev=SREG; |  | ||||||
| #ifdef interrupt_is_disabled |  | ||||||
|   cli();   |  | ||||||
| #endif   |  | ||||||
| 
 |  | ||||||
|   while (datlen--) { |  | ||||||
|     curbyte=*data++; |  | ||||||
|      |  | ||||||
|     asm volatile( |  | ||||||
|     "       ldi   %0,8  \n\t" |  | ||||||
| #ifndef interrupt_is_disabled |  | ||||||
|     "       clt         \n\t" |  | ||||||
| #endif |  | ||||||
|     "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; |  | ||||||
| } |  | ||||||
| @ -1,97 +0,0 @@ | |||||||
| /*
 |  | ||||||
|  * light weight WS2812 lib include |  | ||||||
|  * |  | ||||||
|  * Version 2.3  - Nev 29th 2015 |  | ||||||
|  * 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> |  | ||||||
| 
 |  | ||||||
| ///////////////////////////////////////////////////////////////////////
 |  | ||||||
| // Define Reset time in µs.
 |  | ||||||
| //
 |  | ||||||
| // This is the time the library spends waiting after writing the data.
 |  | ||||||
| //
 |  | ||||||
| // WS2813 needs 300 µs reset time
 |  | ||||||
| // WS2812 and clones only need 50 µs
 |  | ||||||
| //
 |  | ||||||
| ///////////////////////////////////////////////////////////////////////
 |  | ||||||
| #if !defined(ws2812_resettime) |  | ||||||
| #define ws2812_resettime    300 |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| ///////////////////////////////////////////////////////////////////////
 |  | ||||||
| // Define I/O pin
 |  | ||||||
| ///////////////////////////////////////////////////////////////////////
 |  | ||||||
| #if !defined(ws2812_port) |  | ||||||
| #define ws2812_port D   // Data port
 |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| #if !defined(ws2812_pin) |  | ||||||
| #define ws2812_pin  5   // Data out pin
 |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| /*
 |  | ||||||
|  *  Structure of the LED array |  | ||||||
|  * |  | ||||||
|  * cRGB:     RGB  for WS2812S/B/C/D, SK6812, SK6812Mini, SK6812WWA, APA104, APA106 |  | ||||||
|  * cRGBW:    RGBW for SK6812RGBW |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| struct cRGB  { uint8_t g; uint8_t r; uint8_t b; }; |  | ||||||
| struct cRGBW { uint8_t g; uint8_t r; uint8_t b; uint8_t w;}; |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| /* 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); |  | ||||||
| void ws2812_setleds_rgbw(struct cRGBW *ledarray, uint16_t number_of_leds); |  | ||||||
| 
 |  | ||||||
| /* 
 |  | ||||||
|  * 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 |  | ||||||
|  */ |  | ||||||
| #if !defined(CONCAT) |  | ||||||
| #define CONCAT(a, b)            a ## b |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| #if !defined(CONCAT_EXP) |  | ||||||
| #define CONCAT_EXP(a, b)   CONCAT(a, b) |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| #define ws2812_PORTREG  CONCAT_EXP(PORT,ws2812_port) |  | ||||||
| #define ws2812_DDRREG   CONCAT_EXP(DDR,ws2812_port) |  | ||||||
| 
 |  | ||||||
| #endif /* LIGHT_WS2812_H_ */ |  | ||||||
| @ -1,98 +0,0 @@ | |||||||
| #include "mma8653.h" |  | ||||||
| #include <util/twi.h> |  | ||||||
| 
 |  | ||||||
| #define AXL_ADDR 0x1D |  | ||||||
| #define AXL_ERR_RET(e) if(1){err = e; goto err;} |  | ||||||
| 
 |  | ||||||
| #define TRY(c) if(1){ret = c; if (ret) return c;} |  | ||||||
| static int mma8653_i2c_transfer(int write, uint8_t reg, uint8_t *data, uint8_t length) |  | ||||||
| { |  | ||||||
| 	int err = 0; |  | ||||||
| 	 |  | ||||||
| 	// WRITE TARGET REGISTER
 |  | ||||||
| 	// Send start
 |  | ||||||
| 	TWCR = (1<<TWINT) | (1<<TWSTA) | (1 << TWEN); |  | ||||||
| 	while (!(TWCR & (1<<TWINT))); |  | ||||||
| 	if ((TWSR & 0xF8) != TW_START) |  | ||||||
| 		AXL_ERR_RET(1); |  | ||||||
| 	// Send device address
 |  | ||||||
| 	TWDR = (AXL_ADDR << 1); |  | ||||||
| 	TWCR = (1<<TWINT) | (1<<TWEN); |  | ||||||
| 	while (!(TWCR & (1<<TWINT))); |  | ||||||
| 	if ((TWSR & 0xF8) != TW_MT_SLA_ACK) |  | ||||||
| 		AXL_ERR_RET(2); |  | ||||||
| 	// Write register address
 |  | ||||||
| 	TWDR = reg; |  | ||||||
| 	TWCR = (1<<TWINT) | (1<<TWEN); |  | ||||||
| 	while (!(TWCR & (1<<TWINT))); |  | ||||||
| 	if ((TWSR & 0xF8) != TW_MT_DATA_ACK) |  | ||||||
| 		AXL_ERR_RET(3); |  | ||||||
| 
 |  | ||||||
| 	if (!write) { |  | ||||||
| 		// Get data
 |  | ||||||
| 		// Send re-start
 |  | ||||||
| 		TWCR = (1<<TWINT) | (1<<TWSTA) | (1 << TWEN); |  | ||||||
| 		while (!(TWCR & (1<<TWINT))); |  | ||||||
| 		if ((TWSR & 0xF8) != TW_REP_START) |  | ||||||
| 			AXL_ERR_RET(4); |  | ||||||
| 		// Command a read cycle
 |  | ||||||
| 		TWDR = (AXL_ADDR << 1) | (!write); |  | ||||||
| 		TWCR = (1<<TWINT) | (1<<TWEN); |  | ||||||
| 		while (!(TWCR & (1<<TWINT))); |  | ||||||
| 		if ((TWSR & 0xF8) != (write ? TW_MT_SLA_ACK : TW_MR_SLA_ACK)) |  | ||||||
| 			AXL_ERR_RET(5); |  | ||||||
| 	} |  | ||||||
| 	while (length--) { |  | ||||||
| 		if (write) { |  | ||||||
| 			TWDR = *(data++); |  | ||||||
| 			TWCR = (1<<TWINT) | (1<<TWEN); |  | ||||||
| 			while (!(TWCR & (1<<TWINT))); |  | ||||||
| 			if ((TWSR & 0xF8) != TW_MT_DATA_ACK) |  | ||||||
| 				AXL_ERR_RET(6); |  | ||||||
| 		} else { |  | ||||||
| 			// Read byte
 |  | ||||||
| 			TWCR = (1<<TWINT) | (1<<TWEN) | ( (length != 0) << TWEA); |  | ||||||
| 			while (!(TWCR & (1<<TWINT))); |  | ||||||
| 			if ((TWSR & 0xF8) != (length != 0 ? TW_MR_DATA_ACK : TW_MR_DATA_NACK)) |  | ||||||
| 				AXL_ERR_RET(6); |  | ||||||
| 			*(data++) = TWDR; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	// Send stop
 |  | ||||||
| 	TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO); |  | ||||||
| 	while (TWCR & (1<<TWSTO)); |  | ||||||
| 	 |  | ||||||
| 	return 0; |  | ||||||
| 	 |  | ||||||
| 	err: |  | ||||||
| 		TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO); // Send stop to abort
 |  | ||||||
| 		return err; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static inline int mma8653_i2c_write(uint8_t reg, uint8_t value) |  | ||||||
| { |  | ||||||
| 	return mma8653_i2c_transfer(1, reg, &value, 1); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int mma8653_init() { |  | ||||||
| 	int ret; |  | ||||||
| 
 |  | ||||||
| 	TWBR = 0xff; |  | ||||||
| 	//TWSR = 3;
 |  | ||||||
| 
 |  | ||||||
| 	TRY(mma8653_i2c_write(0x2A, (1 << 1) | (1 << 0))); |  | ||||||
| 	TRY(mma8653_i2c_write(0x2B, (1 << 7))); // Test mode en
 |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int mma8653_get_measurements(struct axl_result *measurements) { |  | ||||||
| 	int ret; |  | ||||||
| 	int8_t buffer[4]; |  | ||||||
| 
 |  | ||||||
| 	TRY(mma8653_i2c_transfer(0, 0x0, (uint8_t*) buffer, 4)); |  | ||||||
| 	measurements->x = buffer[1]; |  | ||||||
| 	measurements->y = buffer[2]; |  | ||||||
| 	measurements->z = buffer[3]; |  | ||||||
| 
 |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| @ -1,13 +0,0 @@ | |||||||
| #ifndef _MMA8653_H |  | ||||||
| #define _MMA8653_H |  | ||||||
| 
 |  | ||||||
| #include "light_ws2812.h" |  | ||||||
| 
 |  | ||||||
| struct axl_result { |  | ||||||
| 	int x, y, z; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| int mma8653_init(); |  | ||||||
| int mma8653_get_measurements(struct axl_result *measurements); |  | ||||||
| 
 |  | ||||||
| #endif |  | ||||||
| @ -1,122 +0,0 @@ | |||||||
| #include "pm.h" |  | ||||||
| 
 |  | ||||||
| #include <avr/io.h> |  | ||||||
| #include <util/delay.h> |  | ||||||
| #include <avr/sleep.h> |  | ||||||
| #include <avr/interrupt.h> |  | ||||||
| 
 |  | ||||||
| void pm_reset() |  | ||||||
| { |  | ||||||
| 	DDRB = 0; |  | ||||||
| 	DDRC = 0; |  | ||||||
| 	DDRD = 0; |  | ||||||
| 	PORTB = 0; |  | ||||||
| 	PORTC = 0; |  | ||||||
| 	PORTD = 0; |  | ||||||
| 	 |  | ||||||
| 	GICR = 0; |  | ||||||
| 
 |  | ||||||
| 	// Reset to bootloader
 |  | ||||||
| 	WDTCR = (1 << WDE) | (1 << WDP2); |  | ||||||
| 	while(1); |  | ||||||
| 
 |  | ||||||
| 	/*
 |  | ||||||
| 	// Reset to application
 |  | ||||||
| 	asm("ldi R16,0x00"); |  | ||||||
| 	asm("push R16"); |  | ||||||
| 	asm("push R16"); |  | ||||||
| 	asm("push R16"); |  | ||||||
| 	asm("push R16"); |  | ||||||
| 	asm("ret"); |  | ||||||
| 	while (1); |  | ||||||
| 	*/ |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void pm_axl_on() |  | ||||||
| { |  | ||||||
| 	HAL_ON(AXL_EN); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void pm_axl_off() |  | ||||||
| { |  | ||||||
| 	HAL_OFF(AXL_EN); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void pm_init() |  | ||||||
| { |  | ||||||
| 	cli(); |  | ||||||
| 
 |  | ||||||
| 	HAL_INIT(VBUS_SENSE, INPUT, OFF); // USB connected indicator
 |  | ||||||
| 	HAL_INIT(VLED_EN_N, OUTPUT, OFF_N); // VLED DCDC converter enable
 |  | ||||||
| 	HAL_INIT(CHG_ACTIVE_N, INPUT, ON); // Battery charging status input
 |  | ||||||
| 	HAL_INIT(BAT_SENSE, INPUT, OFF); // No pull-up on Batt sense ADC input
 |  | ||||||
| 	HAL_INIT(BAT_SENSE_EN_N, INPUT, OFF); // Disable using High-Z
 |  | ||||||
| 	HAL_INIT(AXL_EN, OUTPUT, OFF); // Turn off AXL
 |  | ||||||
| 	HAL_INIT(AXL_I2C, INPUT, OFF); // No Pull-ups on I2C
 |  | ||||||
| 
 |  | ||||||
| 	// Hardware bug after sleep. Need to manually turn off->on I2C transceiver.
 |  | ||||||
| 	TWCR &= ~((1 << TWSTO) | (1 << TWEN)); |  | ||||||
| 	 |  | ||||||
| 	sei(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void pm_disable_periphery() |  | ||||||
| { |  | ||||||
| 	cli(); |  | ||||||
| 
 |  | ||||||
| 	// Turn off HW
 |  | ||||||
| 	TCCR1B = 0; |  | ||||||
| 	TIMSK = 0; |  | ||||||
| 	WDTCR = 0; |  | ||||||
| 	TWCR = 0; |  | ||||||
| 	SPCR = 0; |  | ||||||
| 	ADCSRA = 0; |  | ||||||
| 
 |  | ||||||
| 	DDRB = 0; |  | ||||||
| 	DDRC = 0; |  | ||||||
| 	DDRD = 0; |  | ||||||
| 	PORTB = 0; |  | ||||||
| 	PORTC = 0; |  | ||||||
| 	PORTD = 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void pm_suspend() |  | ||||||
| { |  | ||||||
| 	pm_disable_periphery(); |  | ||||||
| 
 |  | ||||||
| 	// Activate wake from button
 |  | ||||||
| 	HAL_INIT(BUTTON_N, INPUT, ON); // Pull-up for user button
 |  | ||||||
| 	MCUCR = (1 << SM1) | (1 << SE); |  | ||||||
| 
 |  | ||||||
| 	sei(); |  | ||||||
| 	sleep_cpu(); |  | ||||||
| 	cli(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void pm_led_on_auto() |  | ||||||
| { |  | ||||||
| 	if (pm_ac_connected()) |  | ||||||
| 		pm_led_off(); |  | ||||||
| 	else |  | ||||||
| 		pm_led_on(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void pm_led_on() |  | ||||||
| { |  | ||||||
| 	HAL_ON_N(VLED_EN_N); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void pm_led_off() |  | ||||||
| { |  | ||||||
| 	HAL_OFF_N(VLED_EN_N); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int pm_ac_connected() |  | ||||||
| { |  | ||||||
| 	return HAL_ASSERTED(VBUS_SENSE); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int pm_charging() |  | ||||||
| { |  | ||||||
| 	return HAL_ASSERTED_N(CHG_ACTIVE_N); |  | ||||||
| } |  | ||||||
| @ -1,22 +0,0 @@ | |||||||
| #ifndef _PM_H |  | ||||||
| #define _PM_H |  | ||||||
| 
 |  | ||||||
| #include "hal.h" |  | ||||||
| 
 |  | ||||||
| void pm_reset(); |  | ||||||
| void pm_init(); |  | ||||||
| void pm_suspend(); |  | ||||||
| 
 |  | ||||||
| void pm_axl_on(); |  | ||||||
| void pm_axl_off(); |  | ||||||
| 
 |  | ||||||
| void pm_led_on(); |  | ||||||
| void pm_led_off(); |  | ||||||
| void pm_led_on_auto(); |  | ||||||
| 
 |  | ||||||
| int pm_ac_connected(); |  | ||||||
| int pm_charging(); |  | ||||||
| 
 |  | ||||||
| void pm_disable_periphery(); |  | ||||||
| 
 |  | ||||||
| #endif |  | ||||||
| @ -1,91 +0,0 @@ | |||||||
| #include <avr/io.h> |  | ||||||
| #include <avr/wdt.h> |  | ||||||
| #include <util/delay.h> |  | ||||||
| #include <string.h> |  | ||||||
| #include <stdlib.h> |  | ||||||
| 
 |  | ||||||
| #include "system.h" |  | ||||||
| #include "pm.h" |  | ||||||
| 
 |  | ||||||
| extern void app_init(); |  | ||||||
| extern void app_suspend(); |  | ||||||
| extern enum app_return app_mainloop(); |  | ||||||
| 
 |  | ||||||
| struct cRGB led[STRIPLEN]; |  | ||||||
| 
 |  | ||||||
| void display_update() { |  | ||||||
| 	ws2812_setleds(led, STRIPLEN); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void display_clear() { |  | ||||||
| 	memset(led, 0, STRIPLEN * 3); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void system_init() |  | ||||||
| { |  | ||||||
| 	pm_disable_periphery(); |  | ||||||
| 	button_init(); |  | ||||||
| 	TIFR = 0xFF; // Clear all interrupt flags
 |  | ||||||
| 	pm_init(); |  | ||||||
| 	pm_axl_on(); |  | ||||||
| 	_delay_ms(50); |  | ||||||
| 	mma8653_init(); |  | ||||||
| 	while (HAL_ASSERTED_N(BUTTON_N)) // Prevent boot while button is pressed
 |  | ||||||
| 		_delay_ms(25); |  | ||||||
| 	timers_init(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| enum BOOT_COLOR {RED, BLUE, GREEN}; |  | ||||||
| void boot_animation(enum BOOT_COLOR color_offset) |  | ||||||
| { |  | ||||||
| 	_delay_ms(10); |  | ||||||
| 	display_clear(); |  | ||||||
| 	for(int i = 0; i<STRIPLEN; ++i) { |  | ||||||
| 		wdt_reset(); |  | ||||||
| 		*(&led[i].r + color_offset) = 0x10; |  | ||||||
| 		display_update(); |  | ||||||
| 		_delay_ms(15); |  | ||||||
| 		*(&led[i].r + color_offset) = 0x0; |  | ||||||
| 	} |  | ||||||
| 	display_update(); |  | ||||||
| 	_delay_ms(10); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void system_boot() |  | ||||||
| { |  | ||||||
| 	system_init(); |  | ||||||
| 	pm_led_on_auto(); |  | ||||||
| 	wdt_enable(WDTO_1S); |  | ||||||
| 	boot_animation(GREEN); |  | ||||||
| 	app_init(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void system_suspend() |  | ||||||
| { |  | ||||||
| 	app_suspend(); |  | ||||||
| 	boot_animation(RED); |  | ||||||
| 	wdt_disable(); |  | ||||||
| 	pm_suspend(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int main() |  | ||||||
| { |  | ||||||
| 	enum app_return ar; |  | ||||||
| 
 |  | ||||||
| 	while (1) { |  | ||||||
| 		system_boot(); |  | ||||||
| 		while ((ar = app_mainloop()) == RUN) { |  | ||||||
| 			wdt_reset(); |  | ||||||
| 		} |  | ||||||
| 		// TODO: Handle reset instead of suspend
 |  | ||||||
| 		system_suspend(); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	pm_reset(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void systick_cb() |  | ||||||
| { |  | ||||||
| 	pm_led_on_auto(); // Turn off LED DC-DC converter when USB power is connected
 |  | ||||||
| 	button_systick_cb(); |  | ||||||
| } |  | ||||||
| @ -1,17 +0,0 @@ | |||||||
| #ifndef _SYSTEM_H |  | ||||||
| #define _SYSTEM_H |  | ||||||
| 
 |  | ||||||
| #include "light_ws2812.h" |  | ||||||
| #include "mma8653.h" |  | ||||||
| #include "timers.h" |  | ||||||
| #include "button.h" |  | ||||||
| 
 |  | ||||||
| #define STRIPLEN (6*9) |  | ||||||
| extern struct cRGB led[STRIPLEN]; |  | ||||||
| 
 |  | ||||||
| void display_update(); |  | ||||||
| void display_clear(); |  | ||||||
| 
 |  | ||||||
| enum app_return {RUN, SUSPEND, RESET}; |  | ||||||
| 
 |  | ||||||
| #endif // _SYSTEM_H
 |  | ||||||
| @ -1,36 +0,0 @@ | |||||||
| #include "timers.h" |  | ||||||
| 
 |  | ||||||
| #include <avr/io.h> |  | ||||||
| #include <avr/interrupt.h> |  | ||||||
| 
 |  | ||||||
| extern void systick_cb(); |  | ||||||
| 
 |  | ||||||
| volatile uint16_t timer[TIMERS_COUNT]; |  | ||||||
| 
 |  | ||||||
| void timers_init() { |  | ||||||
| 	// Configure Systick
 |  | ||||||
| 	TCCR1B = (1 << CS11) | (1 << CS10) | (1 << WGM12); // CLKio / 64, CTC
 |  | ||||||
| 	OCR1A = 250 * SYSTICK_MS; |  | ||||||
| 	TIMSK = (1 << OCIE1A); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| uint8_t block_for(uint8_t channel, uint16_t time_systicks) |  | ||||||
| { |  | ||||||
| 	if (timer_expired(channel)) { |  | ||||||
| 		timer_set(channel, time_systicks); |  | ||||||
| 		return 1; |  | ||||||
| 	} |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| ISR (TIMER1_COMPA_vect) |  | ||||||
| { |  | ||||||
| 	uint8_t i; |  | ||||||
| 	for (i = 0; i < TIMERS_COUNT; ++i) { |  | ||||||
| 		if (timer[i] != 0) { |  | ||||||
| 			timer[i]--; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	systick_cb(); |  | ||||||
| } |  | ||||||
| @ -1,21 +0,0 @@ | |||||||
| #ifndef _TIMERS_H |  | ||||||
| #define _TIMERS_H |  | ||||||
| 
 |  | ||||||
| #include <stdint.h> |  | ||||||
| 
 |  | ||||||
| #define SYSTICK_MS 1 // Systick interval in ms
 |  | ||||||
| enum TIMERS{TIMER_BUTTON, |  | ||||||
| 	    TIMER_APP0, |  | ||||||
| 	    TIMER_APP1, |  | ||||||
| 	    TIMERS_COUNT}; |  | ||||||
| 
 |  | ||||||
| extern volatile uint16_t timer[TIMERS_COUNT]; |  | ||||||
| 
 |  | ||||||
| #define timer_ms(ms) (ms / SYSTICK_MS) |  | ||||||
| #define timer_set(channel, time_systicks) if (1) {timer[channel] = time_systicks;} |  | ||||||
| #define timer_expired(channel) (timer[channel] == 0) |  | ||||||
| 
 |  | ||||||
| void timers_init(); |  | ||||||
| uint8_t block_for(uint8_t channel, uint16_t time_systicks); |  | ||||||
| 
 |  | ||||||
| #endif // _TIMERS_H
 |  | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user