Commit 494fe8623641c783fae30badddcfc3afb2a4a4df
- Diff rendering mode:
- inline
- side by side
Wand/main/accel.h
(11 / 2)
|   | |||
| 1 | // accel.h | ||
| 2 | // | ||
| 3 | // Disney Fantasia Project | ||
| 4 | // | ||
| 5 | // | ||
| 1 | 6 | ||
| 2 | 7 | #ifndef ACCEL_H | |
| 3 | 8 | #define ACCEL_H | |
| 4 | 9 | ||
| 5 | void initAccel(); | ||
| 6 | void pollAccel(accel_data_t *data); | ||
| 10 | #include "fantasia_packets.h" | ||
| 11 | |||
| 12 | void initAccel(); //call with other inits | ||
| 13 | void updateAccel(); //call with other updates | ||
| 14 | void configAccel(fantasia_pkt_t *pkt); //give this all valid config packets, sets up triggers and timing, if it gets a mode==POLL then it sends a data packet to the xBee | ||
| 15 | //void pollAccel(); //depreciated, gave direct access to the data, instead it is just called internally and the packet is sent in accel.pde | ||
| 7 | 16 | ||
| 8 | 17 | #endif |
Wand/main/accel.pde
(115 / 54)
|   | |||
| 1 | #define AVERAGE 16 | ||
| 1 | // accel.pde | ||
| 2 | // | ||
| 3 | // Disney Fantasia Project | ||
| 4 | // | ||
| 5 | // | ||
| 2 | 6 | ||
| 3 | volatile uint16_t x, y, z; | ||
| 7 | #include "accel.h" | ||
| 8 | #include "fantasia_packets.h" | ||
| 9 | #include <XBeeReader.h> | ||
| 4 | 10 | ||
| 5 | //volatile static void (*tiggerAccel)(); | ||
| 11 | //Exponential running average 2^N | ||
| 12 | #define AVERAGE 2 | ||
| 6 | 13 | ||
| 7 | //ADC sampling complete interrupt | ||
| 8 | SIGNAL(ADC_vect){ | ||
| 14 | //modes | ||
| 15 | uint8_t mode; | ||
| 16 | #define OFF 0 | ||
| 17 | #define POLL 1 | ||
| 18 | #define TIMER 2 | ||
| 19 | #define TRIGGER 3 | ||
| 9 | 20 | ||
| 10 | //disable interrupts (keeps interrupts from nesting) | ||
| 11 | cli(); | ||
| 21 | //gloabl storage | ||
| 22 | volatile uint16_t x, y, z; | ||
| 23 | volatile uint32_t trigger; | ||
| 24 | volatile uint8_t timer_period; | ||
| 25 | volatile uint32_t timer_target; | ||
| 12 | 26 | ||
| 13 | // When we try to change the ADC Channel (by setting ADMUX) the next capture has already started | ||
| 14 | // And so the channel change won't take effect until one cycle later. | ||
| 15 | // When the next ADC_vect is triggered then it will have the value from the old channel but ADMUX | ||
| 16 | // will point to the new channel | ||
| 17 | // Since this code changes the channel on every cycle it means ADMUX is always one step ahead of us | ||
| 18 | // so the reading for y (ADMUX&0x0F==4) is actually the value of x, etc. | ||
| 19 | // That is why the cases do not match | ||
| 27 | //externs | ||
| 28 | extern uint8_t cur_app; | ||
| 29 | extern XBeeReader xbee; | ||
| 20 | 30 | ||
| 21 | //Mask the ADC mux to see what channel we just read from (give or take) | ||
| 22 | uint8_t test = (ADMUX&0x0F); | ||
| 31 | //MACROS | ||
| 32 | #define SQUARE(x) (x>512)?((x-512)*(x-512)):((512-x)*(512-x)) | ||
| 23 | 33 | ||
| 24 | switch(test){ | ||
| 25 | case 4: //X-axis | ||
| 26 | x= ((AVERAGE-1)*x+ADCW)/AVERAGE; | ||
| 27 | ADMUX = 0x45; | ||
| 28 | break; | ||
| 29 | case 5: //Y-axis | ||
| 30 | y= ((AVERAGE-1)*y+ADCW)/AVERAGE; | ||
| 31 | ADMUX = 0x43; | ||
| 32 | break; | ||
| 33 | case 3: //Z-axis | ||
| 34 | z= ((AVERAGE-1)*z+ADCW)/AVERAGE; | ||
| 35 | ADMUX = 0x44; | ||
| 36 | break; | ||
| 37 | } | ||
| 34 | //Acceleromter Packet Type: | ||
| 35 | //TODO: check if this is proper, then put it into the fantasia_packets | ||
| 36 | typedef struct { | ||
| 37 | uint8_t type; | ||
| 38 | uint8_t app_uuid; | ||
| 39 | uint8_t x; | ||
| 40 | uint8_t y; | ||
| 41 | uint8_t z; | ||
| 42 | } accel_data_pkt_t; | ||
| 38 | 43 | ||
| 39 | //re-enable global interrupts | ||
| 40 | sei(); | ||
| 41 | 44 | ||
| 45 | //Sets up the trigger function pointer and intializes the vars | ||
| 46 | void initAccel(){//void(*tiggerFunc)(void)){ | ||
| 47 | |||
| 48 | //No ADC setup done here, not sure if this is correct | ||
| 49 | //No interrupt setup done here, we'll do it without instead | ||
| 50 | //initialize everything to 0: | ||
| 51 | x=512; | ||
| 52 | y=512; | ||
| 53 | z=512; | ||
| 54 | mode=OFF; | ||
| 55 | |||
| 42 | 56 | } | |
| 43 | 57 | ||
| 44 | 58 | ||
| 45 | //Initilizes all ADC stuff | ||
| 46 | //Sets up the trigger function pointer | ||
| 47 | void initAccel(){//void(*tiggerFunc)(void)){ | ||
| 59 | //returns averaged ADC values | ||
| 60 | //Called during poll or by timer | ||
| 61 | //Sends a packets | ||
| 62 | void pollAccel(){ | ||
| 63 | |||
| 64 | accel_data_pkt_t pkt; | ||
| 65 | |||
| 66 | //setup the packet data | ||
| 67 | pkt.type = ACCEL_DATA; | ||
| 68 | pkt.app_uuid = cur_app; | ||
| 69 | |||
| 70 | //perform the 45 degree transformation: | ||
| 71 | pkt.x=((0x1FE - (y>>2) - (x>>2)) * 181)>>8; | ||
| 72 | pkt.y=(((y>>2) + 0xFF - (x>>2)) * 181)>>8; | ||
| 73 | pkt.z=0xFF-(z>>2); | ||
| 74 | |||
| 75 | //check for overflow in x/y: | ||
| 76 | if((x+y)<600){pkt.x=0xFF;} | ||
| 77 | if((y-y)>420){pkt.y=0xFF;} | ||
| 78 | |||
| 79 | //send out the packet: | ||
| 80 | xbee.sendZ( (*uint8_t)&pkt, sizeof(accel_data_pkt_t) ); | ||
| 48 | 81 | ||
| 49 | //setup ADC in free running mode (see datasheet) | ||
| 50 | ADMUX = 0x44; // 8b 01 0 x 0100 (aVCC RightAdjust x Channel 4) | ||
| 51 | ADCSRB = 0x0; // 8b x 0 xxx 000 (x ACME xxx FreeRunningMode) | ||
| 52 | ADCSRA = 0xE8; // 8b 1 1 1 x 1 000 (EnableADC Start EnableTrigger x EnableInt clk/2) | ||
| 53 | x=0; | ||
| 54 | y=0; | ||
| 55 | z=0; | ||
| 56 | //tiggerAccel=triggerFunc; | ||
| 57 | |||
| 58 | 82 | } | |
| 59 | 83 | ||
| 84 | //Called during the update loop | ||
| 85 | //Handles trigger and timer | ||
| 86 | //actually reads acceleromter | ||
| 87 | void updateAccel(){ | ||
| 88 | |||
| 89 | //check if we need the accelerometer | ||
| 90 | if(mode!=OFF){ | ||
| 91 | //Update the acceleromter globals using the EMA | ||
| 92 | x = ((1<<AVERAGE-1)*x+analogRead(accel_x))>>AVERAGE; | ||
| 93 | y = ((1<<AVERAGE-1)*y+analogRead(accel_y))>>AVERAGE; | ||
| 94 | z = ((1<<AVERAGE-1)*z+analogRead(accel_z))>>AVERAGE; | ||
| 95 | |||
| 96 | //If we are in trigger mode, check to see if we've triggered | ||
| 97 | if(mode==TRIGGER){ | ||
| 98 | if(trigger<SQUARE(x)+SQUARE(y)+SQUARE(z)){ | ||
| 99 | //send a packet | ||
| 100 | pollAccel(); | ||
| 101 | } | ||
| 102 | } | ||
| 103 | |||
| 104 | if(mode==TIMER){ | ||
| 105 | if(millis()>timer_target){ | ||
| 106 | //send a packet | ||
| 107 | timer_target += timer_period; | ||
| 108 | pollAccel(); | ||
| 109 | } | ||
| 110 | } | ||
| 111 | } | ||
| 60 | 112 | ||
| 61 | //returns ADC values (not averaged yet) | ||
| 62 | //Called during poll or by timer | ||
| 63 | void pollAccel(accel_data_t *data){ | ||
| 113 | } | ||
| 64 | 114 | ||
| 65 | //this is a pirimitive form of mutexing | ||
| 66 | cli(); | ||
| 67 | //perform the 45 degree transformation: | ||
| 68 | data->x=(((0xFF-(y>>2))*181)>>8)+(((0xFF-(x>>2))*181)>>8); | ||
| 69 | data->y=(((y>>2)*181)>>8)+(((0xFF-(x>>2))*181)>>8); | ||
| 70 | data->z=0xFF-(z>>2); | ||
| 71 | sei(); | ||
| 115 | //Accelerometer config | ||
| 116 | //ARGS: just pass us the packet address: | ||
| 117 | void configAccel(fantasia_pkt_t *pkt){ | ||
| 118 | |||
| 119 | mode = pkt->accel_config.mode; | ||
| 120 | |||
| 121 | switch( pkt->accel_config.mode){ | ||
| 122 | case TRIGGER: | ||
| 123 | trigger = (pkt->accel_config.data)<<12; | ||
| 124 | break; | ||
| 125 | case TIMER: | ||
| 126 | timer_period = pkt->accel_config.data; | ||
| 127 | timer_target = millis() + timer_period; | ||
| 128 | break; | ||
| 129 | case POLL: | ||
| 130 | pollAccel(); | ||
| 131 | break; | ||
| 132 | } | ||
| 72 | 133 | ||
| 73 | 134 | } |

