// 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_