// Copyright 2009 Olivier Gillet. // // Author: Olivier Gillet (ol.gillet@gmail.com) // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see . // // ----------------------------------------------------------------------------- // // Debouncing for: // - A single switch. // - An array of switches. #ifndef AVRLIB_DEVICES_SWITCHES_H_ #define AVRLIB_DEVICES_SWITCHES_H_ #include #include "avrlib/devices/shift_register.h" #include "avrlib/size_to_type.h" namespace avrlib { template class DebouncedSwitch { public: DebouncedSwitch() { } static inline void Init() { Input::set_mode(DIGITAL_INPUT); if (enable_pull_up) { Input::High(); } state_ = 0xff; } // To be called at a rate < 1000 Hz. static inline uint8_t Read() { state_ = (state_ << 1) | Input::value(); return state_; } static inline uint8_t lowered() { return state_ == 0x80; } static inline uint8_t raised() { return state_ == 0x7f; } static inline uint8_t high() { return state_ == 0xff; } static inline uint8_t low() { return state_ == 0x00; } static inline uint8_t state() { return state_; } static inline uint8_t immediate_value() { return Input::value(); } private: static uint8_t state_; DISALLOW_COPY_AND_ASSIGN(DebouncedSwitch); }; /* static */ template uint8_t DebouncedSwitch::state_; template class DebouncedSwitches { typedef typename DataTypeForSize::Type T; typedef ShiftRegisterInput< Load, Clock, Data, 8 * sizeof(T), order> Register; public: DebouncedSwitches() { } static inline void Init() { Register::Init(); memset(state_, 0xff, sizeof(state_)); } static inline T ReadRegister() { return Register::Read(); } static inline void Process(T value) { T mask = 1 << (num_inputs - 1); for (uint8_t i = 0; i < num_inputs; ++i) { state_[i] <<= 1; if (value & mask) { state_[i] |= 1; } mask >>= 1; } } static inline void Read() { Process(ReadRegister()); } static inline uint8_t lowered(uint8_t index) { return state_[index] == 0x80; } static inline uint8_t raised(uint8_t index) { return state_[index] == 0x7f; } static inline uint8_t high(uint8_t index) { return state_[index] == 0xff; } static inline uint8_t low(uint8_t index) { return state_[index] == 0x00; } static inline uint8_t state(uint8_t index) { return state_[index]; } static inline int8_t event(uint8_t index) { if (lowered(index)) { return -1; } else if (raised(index)) { return 1; } return 0; } private: static uint8_t state_[num_inputs]; DISALLOW_COPY_AND_ASSIGN(DebouncedSwitches); }; template uint8_t DebouncedSwitches::state_[num_inputs]; } // namespace avrlib #endif // AVRLIB_DEVICES_SWITCHES_H_