Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <avr/interrupt.h>
- #include <avr/io.h>
- #include <avr/pgmspace.h>
- #include <avr/iom32.h>
- #include <util/delay.h>
- #define INTERVALS_HALF_HOUR 1024 //example
- #define BLIND_LEVELS 4
- #define INTENSITY_MAX 255
- #define LED_DDR DDRB
- #define LED_PORT PORTB
- #define ENABLE_LED(x) LED_PORT |= (1 << (char)(x))
- #define DISABLE_LED(x) LED_PORT &= ~(1 << (char)(x))
- #define SET_MODE(x) current_mode = x; \
- LED_PORT &= 0b11110000; \
- ENABLE_LED(x)
- #define BUTTON_DDR DDRC
- #define BUTTON_PORT PORTC
- #define BUTTON_PIN PINC
- #define TEST_BUTTON(x) BUTTON_PIN & (1 << (char)(x))
- typedef enum {
- MODE_MANUAL = 0,
- MODE_AUTO_WARM = 1,
- MODE_AUTO_COOL = 2,
- MODE_CALIBRATE = 3,
- MODE_SENTINEL = 4 //invalid mode
- } blind_mode;
- typedef enum {
- BUTTON_MODE = 0, //0b000
- BUTTON_UP = 1, //0b001
- BUTTON_DOWN = 2, //0b010
- BUTTON_CALIBRATE = 3, //0b011
- BUTTON_NONE = 4, //0b100
- BUTTON_SENTINEL = 5 //invalid button
- } button_input;
- int current_position; //the current "position" the blind is in
- int position_levels[BLIND_LEVELS]; //an array of the intervals we should keep our blind at
- int max_position; //the maximum "position" we can extend the blind to
- int intensity_levels[BLIND_LEVELS];
- int current_intensity; // 0 - 3 (representing intensity classes)
- int interval_since_move; //how long it's been since we've last moved
- blind_mode current_mode;
- //prototypes
- void manual_mode(void);
- void auto_mode(void);
- unsigned char check_intensity_level(void);
- void calibrate_mode(void);
- button_input check_buttons(void);
- void roll(int new_position);
- void toggle_mode(void);
- //implementation
- void setup(void) {
- int i;
- //Set up data direction registers
- LED_DDR = 0xFF; // LEDs all output.
- BUTTON_DDR = 0x00; // Port A all inputs.
- BUTTON_PORT = 0xFF; // stop any pullups.
- //Set up interrupts
- //give time for DDRs
- _delay_ms(1);
- //Set up intensity classes
- intensity_levels[0] = (INTENSITY_MAX + 1) / BLIND_LEVELS;
- for (i = 1; i < BLIND_LEVELS; i++)
- intensity_levels[i] = intensity_levels[0] * i;
- //put unit manual mode by default
- current_mode = MODE_MANUAL;
- //indicate current mode
- ENABLE_LED(current_mode);
- }
- int main(void) {
- //initialise system
- setup();
- for( ; ; ) {
- switch (current_mode) {
- case MODE_MANUAL:
- manual_mode();
- break;
- case MODE_AUTO_WARM:
- case MODE_AUTO_COOL:
- auto_mode();
- break;
- case MODE_CALIBRATE:
- calibrate_mode();
- break;
- default:
- toggle_mode();
- break;
- }
- }
- return 0;
- }
- void manual_mode(void) {
- button_input input;
- while (MODE_MANUAL == current_mode) {
- input = check_buttons();
- if (BUTTON_UP == input) {
- //roll up
- ENABLE_LED(7);
- } else {
- DISABLE_LED(7);
- }
- if (BUTTON_DOWN == input) {
- //roll down
- ENABLE_LED(6);
- } else {
- DISABLE_LED(6);
- }
- //check if user is changing mode
- toggle_mode();
- }
- }
- void auto_mode(void) {
- int intensity_level, new_position_level = -1;
- while (MODE_AUTO_WARM == current_mode || MODE_AUTO_COOL == current_mode) {
- /*
- if (interval_since_move > INTERVALS_HALF_HOUR) {
- //we have waited long enough, check if we should move
- intensity_level = check_intensity_level();
- if (intensity_level != current_intensity) {
- if (MODE_AUTO_WARM == current_mode)
- new_position_level = (BLIND_LEVELS - 1) - intensity_level;
- else if (MODE_AUTO_COOL == current_mode) {
- new_position_level = intensity_level;
- roll(position_levels[new_position_level]);
- }
- }
- }
- */
- //check if user is changing mode
- toggle_mode();
- }
- }
- //reads LDR and returns the intensity interval of the sensed light
- unsigned char check_intensity_level(void) {
- unsigned char intensity = 0; //READ INTENSITY FROM SENSOR
- //SOME DAA / ADD IO
- return intensity / ((INTENSITY_MAX + 1) / BLIND_LEVELS);
- }
- void calibrate_mode(void) {
- int i;
- //set position = max_position = 0
- //start timer
- while (BUTTON_CALIBRATE == check_buttons()) {
- //keep counting
- //(timer interrupt function will continue adding to position)
- }
- //end timer
- //save max_position = position
- /*
- position_levels[0] = max_position / BLIND_LEVELS;
- for (i = 1; i < BLIND_LEVELS; i++)
- position_levels[i] = position_levels[0] * i;
- */
- //return to manual mode
- SET_MODE(MODE_MANUAL);
- }
- button_input check_buttons(void) {
- char mask = 1, input, i;
- //read button port (inverted because buttons are low when pressed)
- input = ~BUTTON_PIN;
- for (i = 0; i < BUTTON_NONE; i++) {
- if (input & mask)
- return (button_input)i;
- mask = mask << 1;
- }
- //no button being pressed
- return BUTTON_NONE;
- }
- void roll(int new_position) {
- //if new_position > current position, roll down
- //if new_position < current position, roll up
- new_position++;
- return;
- }
- void toggle_mode(void) {
- button_input button;
- button = check_buttons();
- switch (button) {
- case BUTTON_NONE:
- //no button pressed
- return;
- case BUTTON_MODE:
- //go to next toggle-able mode (manual, warm, cool)
- current_mode = (current_mode + 1) % BUTTON_CALIBRATE;
- break;
- case BUTTON_CALIBRATE:
- //go to calibrate mode
- current_mode = MODE_CALIBRATE;
- break;
- default:
- //unrelated button pressed
- return;
- }
- //update LED
- SET_MODE(current_mode);
- //delay to be sure
- _delay_ms(100);
- //wait until button is released
- while (BUTTON_NONE != check_buttons());
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement