wip: Leddie FW
This commit is contained in:
		
							parent
							
								
									3ffd686b57
								
							
						
					
					
						commit
						5849f8441b
					
				
							
								
								
									
										3
									
								
								firmware/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								firmware/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| *.o | ||||
| *.bin | ||||
| *.hex | ||||
							
								
								
									
										21
									
								
								firmware/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								firmware/Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | ||||
| MCU=atmega8 | ||||
| CFLAGS=-g -Wall --param=min-pagesize=0 -mcall-prologues -mmcu=$(MCU) -Os -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 main.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 | ||||
							
								
								
									
										45
									
								
								firmware/lib/hal.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								firmware/lib/hal.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,45 @@ | ||||
| #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_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_INIT(name, type, default) HAL_##default(name); HAL_##type(name) | ||||
| 
 | ||||
| #define PORT_VLED_EN_N(t) t##B | ||||
| #define PIN_VLED_EN_N (1 << 4) // TODO
 | ||||
| 
 | ||||
| #define PORT_CHG_ACTIVE_N(t) t##B | ||||
| #define PIN_CHG_ACTIVE_N (1 << 5) // TODO
 | ||||
| 
 | ||||
| 
 | ||||
| #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 | ||||
							
								
								
									
										194
									
								
								firmware/lib/light_ws2812.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										194
									
								
								firmware/lib/light_ws2812.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,194 @@ | ||||
| /*
 | ||||
| * 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; | ||||
| } | ||||
							
								
								
									
										97
									
								
								firmware/lib/light_ws2812.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								firmware/lib/light_ws2812.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,97 @@ | ||||
| /*
 | ||||
|  * 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_ */ | ||||
							
								
								
									
										111
									
								
								firmware/lib/mma8653.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								firmware/lib/mma8653.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,111 @@ | ||||
| #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]; | ||||
| /*
 | ||||
| 	led[0].r = buffer[1] > 0; | ||||
| 	led[1].r = buffer[2] > 0; | ||||
| 	led[2].r = buffer[3] > 0; | ||||
| 	 | ||||
| 	led[5].r = !!(buffer[0] & 1); // 0
 | ||||
| 	led[5].g = !!(buffer[0] & 2); // 1
 | ||||
| 	led[5].b = !!(buffer[0] & 4); // 2
 | ||||
| 	led[4].r = !!(buffer[0] & 8); // 3
 | ||||
| 	led[4].g = !!(buffer[0] & 16); // 4
 | ||||
| 	led[4].b = !!(buffer[0] & 32); // 5
 | ||||
| 	led[3].r = !!(buffer[0] & 64); // 6
 | ||||
| 	led[3].g = !!(buffer[0] & 128); // 7
 | ||||
| */ | ||||
| 	return 0; | ||||
| } | ||||
							
								
								
									
										13
									
								
								firmware/lib/mma8653.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								firmware/lib/mma8653.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | ||||
| #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 | ||||
							
								
								
									
										102
									
								
								firmware/lib/pm.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								firmware/lib/pm.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,102 @@ | ||||
| #include "pm.h" | ||||
| #include "hal.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(); | ||||
| 	 | ||||
| 	DDRB = 0; | ||||
| 	DDRC = 0; | ||||
| 	DDRD = 0; | ||||
| 	PORTB = 0; | ||||
| 	PORTC = 0; | ||||
| 	PORTD = 0; | ||||
| 	 | ||||
| 	HAL_INIT(VLED_EN_N, OUTPUT, OFF_N); // VLED DCDC converter enable
 | ||||
| 	HAL_INIT(CHG_ACTIVE_N, INPUT, OFF); // 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
 | ||||
| 	HAL_INIT(BUTTON_N, INPUT, ON); // Pull-up for user button
 | ||||
| 	 | ||||
| 	GICR = (1 << INT1); | ||||
| 
 | ||||
| 	// Hardware bug after sleep. Need to manually turn off->on I2C transceiver.
 | ||||
| 	TWCR &= ~((1 << TWSTO) | (1 << TWEN)); | ||||
| 	 | ||||
| 	sei(); | ||||
| } | ||||
| 
 | ||||
| static void disable_periphery() | ||||
| { | ||||
| 	cli(); | ||||
| 
 | ||||
| 	WDTCR = 0; | ||||
| 	TWCR = 0; | ||||
| 	SPCR = 0; | ||||
| 	ADCSRA = 0; | ||||
| 
 | ||||
| 	DDRB = 0; | ||||
| 	DDRC = 0; | ||||
| 	DDRD = 0; | ||||
| 	PORTB = 0; | ||||
| 	PORTC = 0; | ||||
| 
 | ||||
| 	HAL_INIT(BUTTON_N, INPUT, ON); // Pull-up for user button
 | ||||
| } | ||||
| 
 | ||||
| void pm_suspend() | ||||
| { | ||||
| 	disable_periphery(); | ||||
| 
 | ||||
| 	//EICRA = 0;
 | ||||
| 	//EIMSK = (1 << INT1);
 | ||||
| 	//SMCR = (1 << SM1) | (1 << SE);
 | ||||
| 
 | ||||
| 	sei(); | ||||
| 	sleep_cpu(); | ||||
| 	cli(); | ||||
| } | ||||
							
								
								
									
										11
									
								
								firmware/lib/pm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								firmware/lib/pm.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| #ifndef _PM_H | ||||
| #define _PM_H | ||||
| 
 | ||||
| void pm_reset(); | ||||
| void pm_init(); | ||||
| void pm_suspend(); | ||||
| 
 | ||||
| void pm_axl_on(); | ||||
| void pm_axl_off(); | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										144
									
								
								firmware/main.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								firmware/main.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,144 @@ | ||||
| #include <avr/io.h> | ||||
| #include <util/delay.h> | ||||
| #include <string.h> | ||||
| 
 | ||||
| #include "lib/light_ws2812.h" | ||||
| #include "lib/pm.h" | ||||
| #include "lib/mma8653.h" | ||||
| 
 | ||||
| #define STRIPLEN 10 | ||||
| struct cRGB led[STRIPLEN]; | ||||
| int brightness = 9; | ||||
| 
 | ||||
| void update() { | ||||
| 	ws2812_setleds(led, STRIPLEN); | ||||
| 	if (!(PIND & (1 << 3))) | ||||
| 		pm_reset(); | ||||
| } | ||||
| 
 | ||||
| int axl_test() | ||||
| { | ||||
| 	int ret; | ||||
| 	int c = 0; | ||||
| 	struct axl_result measurements; | ||||
| 	 | ||||
| 	int dir_x; | ||||
| 	int dir_y; | ||||
| 	int ledno; | ||||
| 	int intens; | ||||
| 	 | ||||
| 	pm_axl_on(); | ||||
| 	_delay_ms(50); | ||||
| 	 | ||||
| 	ret = mma8653_init(); | ||||
| 	if (ret) { | ||||
| 		led[8].b = 0x10; | ||||
| 		update(); | ||||
| 		while(1); | ||||
| 	} | ||||
| 
 | ||||
| 	while(1) { | ||||
| 		c++; | ||||
| 		 | ||||
| 		#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; | ||||
| 
 | ||||
| 		/*if (ret) {
 | ||||
| 			led[8].g = 0; | ||||
| 			led[8].r = c & 1; | ||||
| 		} else { | ||||
| 			led[8].r = 0; | ||||
| 			led[8].g = c & 1; | ||||
| 		}*/ | ||||
| 		update(); | ||||
| 		//_delay_ms(50);
 | ||||
| 		memset(led, 0, 9 * 3); | ||||
| 		//update();
 | ||||
| 		_delay_ms(50); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| int main() | ||||
| {	 | ||||
| 	pm_init(); | ||||
| 	_delay_ms(1); | ||||
| 	 | ||||
| 	memset(led, 0, STRIPLEN * 3); | ||||
| 	for(int i = 0; i<STRIPLEN; ++i) { | ||||
| 		led[i].g = 0x10; | ||||
| 		update(); | ||||
| 		_delay_ms(30); | ||||
| 		led[i].g = 0x0; | ||||
| 	} | ||||
| 	update(); | ||||
| 
 | ||||
| 	axl_test(); | ||||
| 
 | ||||
| 	while (1) { | ||||
| 		led[0].r = brightness; | ||||
| 		led[2].b = 0; | ||||
| 		update(); | ||||
| 		_delay_ms(250); | ||||
| 		 | ||||
| 		led[1].g = brightness; | ||||
| 		led[0].r = 0; | ||||
| 		update(); | ||||
| 		_delay_ms(250); | ||||
| 
 | ||||
| 		led[1].g = 0; | ||||
| 		led[2].b = brightness; | ||||
| 		update(); | ||||
| 		_delay_ms(250); | ||||
| 		 | ||||
| 		for (int i=0; i<STRIPLEN; ++i) { | ||||
| 			led[i].r=brightness; | ||||
| 			led[i].g=brightness; | ||||
| 			led[i].b=brightness; | ||||
| 		} | ||||
| 		update(); | ||||
| 		_delay_ms(50); | ||||
| 		for (int i=0; i<STRIPLEN; ++i) { | ||||
| 			led[i].r=0; | ||||
| 			led[i].g=0; | ||||
| 			led[i].b=0; | ||||
| 		} | ||||
| 		update(); | ||||
| 		_delay_ms(200); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // User button interrupt
 | ||||
| ISR(INT1_vect) | ||||
| { | ||||
| 	pm_reset(); | ||||
| 	return; | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user