#include "TouchScreen.h"
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>
#define NUMSAMPLES 2
// Interruptbedienroutine für Pin-Change (Touchscreen)
// Tut nichts als den Prozessor aufzuwecken
EMPTY_INTERRUPT(PCINT2_vect);
EMPTY_INTERRUPT(ADC_vect);
void TouchScreen::Init() { // nichts tun!
// Vorausgesetzt sei, dass die beteiligten Pins für das Display
// bereits initialisiert (für Ausgabe) sind
PCMSK2|=0x80; // PCINT23 heißmachen
}
// "Ruhezustand" aktivieren
// TODO: Input Disable Register setzen (spart paar µA)
static void setIdling() {
DDRD&=~0x80; // Y- = Z
PORTD=0x80; // Y- = HiZ, Y+ = L
DDRC&=~0x02;
PORTC&=~0x02; // Y+ = Z
PORTC&=~0x04; // X+ = L
_delay_us(0.5);
}
// Ausgangszustand wiederherstellen
static void restorePorts() {
DDRD|=0xC0; // Ausgang
PORTC|=0x06; // HIGH
DDRC|=0x06; // Ausgang
}
bool TouchScreen::isTouching() {
setIdling();
bool ret=!(PIND&0x80); // Drück-Zustand einlesen (TRUE wenn LOW)
restorePorts();
return ret;
}
uint16_t TouchScreen::readTouch(uint8_t b) {
ADCSRA=0x9F; // A/D-Wandler aktivieren mit Teiler 128 -> Taktfrequenz 125 kHz
if (b) { // Y messen
DDRC&=~0x02; PORTC&=~0x02; // X- = Z
PORTC&=~0x04; // Y- = L
DDRD&=~0x80; PORTD&=~0x80; // X+ = Z
PORTD|= 0x40; // Y+ = H
ADMUX=0x41; // ADC1, sonst wie unten
}else{ // X messen
PORTC&=~0x02; // X- = L
DDRC&=~0x04; PORTC&=~0x04; // Y- = Z
PORTD|= 0x80; // X+ = H
DDRD&=~0x40; PORTD&=~0x40; // Y+ = Z
ADMUX=0x42; // ADC2, Referenz 5 V, rechts ausgerichtet
}
_delay_us(0.5);
ADCSRA=0xDF; // A/D-Wandler starten mit Interrupt
do sleep_cpu();
while (ADCSRA&0x40); // warten bis fertig
uint16_t ret=ADC;
ADCSRA=0;
restorePorts();
return ret;
}
// Hier: Nur für Argument -2: Sleep
bool TouchScreen::wait(int ms) {
setIdling();
if (PIND&0x80) { // Finger nicht drauf?
PCIFR=0x04; // Evtl. vorhandenen anhängigen Interrupt löschen
uint8_t o=PCICR;
PCICR|=0x04; // Pegelwechselinterrupt für Touchscreen aktivieren
sleep_cpu();
PCICR=o;
}
restorePorts();
return false;
}
Detected encoding: UTF-8 | 0
|