summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorian Baumann <derflob@derflob.de>2015-12-13 13:06:08 +0100
committerFlorian Baumann <derflob@derflob.de>2015-12-13 13:06:08 +0100
commite8beab06cb7e5e558f9caef9fe8bb230fd86ece2 (patch)
tree4270cce747df681f472fd6a584adaa14220a5dc8
parent48eb385d3e58a9d60234b601a878bf471e4fd109 (diff)
downloadmFeTAp-proto.tar.gz
mFeTAp-proto.tar.bz2
-rw-r--r--mFeTAp.ino513
1 files changed, 275 insertions, 238 deletions
diff --git a/mFeTAp.ino b/mFeTAp.ino
index fe184ac..2542bf2 100644
--- a/mFeTAp.ino
+++ b/mFeTAp.ino
@@ -31,9 +31,18 @@ Adafruit_FONA fona = Adafruit_FONA(FONA_RST);
#define DEFAULT_DIAL_PREFIX "+4989"
+#define DEBOUNCE_DELAY 25
+
+#define DIAL_DELAY 4000
+
+#define RINGING_PERIOD 20
+
+#define SMS_SIGNAL 150
+
volatile int digit = 0;
volatile int digit_dialed = 0;
volatile int digit_dialing = 0;
+unsigned long digit_playing = 0;
volatile int number_dialed = 0;
@@ -41,359 +50,387 @@ char number[NUMBER_LEN] = { '\0' };
int number_len = 0;
enum adv_states {
- IDLE,
- WAIT_FOR_NUMBER,
- DIALING,
- SPEAKING,
-
- BUSY,
- INCOMING,
- READING_SMS,
+ IDLE,
+ WAIT_FOR_NUMBER,
+ DIALING,
+ SPEAKING,
+
+ BUSY,
+ INCOMING,
+ READING_SMS,
} adv_state;
void setup() {
- Serial.begin(9600);
+ Serial.begin(9600);
- pinMode(PIN_DIAL, INPUT_PULLUP);
- pinMode(PIN_DIGIT, INPUT_PULLUP);
+ pinMode(PIN_DIAL, INPUT_PULLUP);
+ pinMode(PIN_DIGIT, INPUT_PULLUP);
- pinMode(PIN_A_BELL, OUTPUT);
- pinMode(PIN_B_BELL, OUTPUT);
+ pinMode(PIN_A_BELL, OUTPUT);
+ pinMode(PIN_B_BELL, OUTPUT);
- pinMode(PIN_INCOMING, INPUT);
+ pinMode(PIN_INCOMING, INPUT);
- pinMode(PIN_HANGUP, INPUT_PULLUP);
+ pinMode(PIN_HANGUP, INPUT_PULLUP);
- pinMode(PIN_LED, OUTPUT);
+ pinMode(PIN_LED, OUTPUT);
- digitalWrite(PIN_A_BELL, LOW);
- digitalWrite(PIN_B_BELL, LOW);
- digitalWrite(PIN_LED, LOW);
+ digitalWrite(PIN_A_BELL, LOW);
+ digitalWrite(PIN_B_BELL, LOW);
+ digitalWrite(PIN_LED, LOW);
- delay(50);
+ delay(50);
- attachInterrupt(INT_DIAL, sig_commit_digit, RISING);
- attachInterrupt(INT_DIGIT, sig_digit, RISING);
+ attachInterrupt(INT_DIAL, sig_commit_digit, RISING);
+ attachInterrupt(INT_DIGIT, sig_digit, RISING);
- fonaSerial->begin(9600);
- fona.begin(*fonaSerial);
+ fonaSerial->begin(9600);
+ fona.begin(*fonaSerial);
- fonaSerial->println("AT+STTONE=1,1,1000");
+ fonaSerial->println("AT+STTONE=1,1,1000");
- enableGSMBusy(false);
+ enableGSMBusy(false);
}
void loop() {
- static long inc_time = 0;
+ static long inc_time = 0;
- if (fonaSerial->available()) {
- Serial.write(fonaSerial->read());
- }
+ while (fonaSerial->available()) {
+ Serial.write(fonaSerial->read());
+ }
- if (Serial.available()) {
- fonaSerial->write(Serial.read());
- }
+ while (Serial.available()) {
+ fonaSerial->write(Serial.read());
+ }
- process_input_RI();
- process_input_hangup();
- process_input_digit();
- process_input_number();
+ process_input_RI();
+ process_input_hangup();
+ process_input_digit();
+ process_input_number();
- process_output_bell();
- process_output_speaker();
+ process_output_bell();
+ process_output_speaker();
}
void process_input_RI() {
- switch (adv_state) {
- case IDLE:
- if (digitalRead(PIN_INCOMING) == LOW) {
- Serial.println("Incoming");
- // TODO: if PIN_INC is low for 200ms it's an SMS
- adv_state = INCOMING;
- }
- break;
- }
+ static unsigned long pin_down = 0;
+
+ switch (adv_state) {
+ case IDLE:
+ if (digitalRead(PIN_INCOMING) == LOW) {
+ if (pin_down == 0) {
+ pin_down = millis();
+ } else {
+ if (millis() - pin_down > SMS_SIGNAL) {
+ Serial.println("INCOMING: Incoming");
+ adv_state = INCOMING;
+ }
+ }
+ } else {
+ if (pin_down > 0 && millis() - pin_down < SMS_SIGNAL) {
+ Serial.println("SMS incoming");
+ // handle SMS
+ pin_down = 0;
+ }
+ }
+ break;
+
+ case INCOMING:
+ if (digitalRead(PIN_INCOMING) == HIGH) {
+ Serial.println("Idle: Left unanswered");
+ adv_state = IDLE;
+ pin_down = 0;
+ }
+ break;
+
+ default:
+ pin_down = 0;
+ break;
+ }
}
void process_input_hangup() {
- switch (adv_state) {
- case IDLE:
- if (digitalRead(PIN_HANGUP) == LOW) {
- Serial.println("Inputting");
- adv_state = WAIT_FOR_NUMBER;
- enableGSMBusy(true);
- delete_number();
- }
- break;
-
- case INCOMING:
- if (digitalRead(PIN_HANGUP) == LOW) {
- Serial.println("Pick up");
- fona.pickUp();
- adv_state = SPEAKING;
- }
- break;
-
- case SPEAKING:
- if (digitalRead(PIN_HANGUP) == HIGH) {
- Serial.println("Hang up");
- fona.hangUp();
- adv_state = IDLE;
- enableGSMBusy(false);
- }
- break;
-
- case WAIT_FOR_NUMBER:
- case DIALING:
- case BUSY:
- if (digitalRead(PIN_HANGUP) == HIGH) {
- MsTimer2::stop();
- Serial.println("Hang up abort");
- delete_number();
- play_dial_tone(false);
- enableGSMBusy(false);
- adv_state = IDLE;
- }
- break;
-
- }
+ switch (adv_state) {
+ case IDLE:
+ if (digitalRead(PIN_HANGUP) == LOW) {
+ Serial.println("WAIT_FOR_NUMBER: Picked up");
+ adv_state = WAIT_FOR_NUMBER;
+ enableGSMBusy(true);
+ delete_number();
+ }
+ break;
+
+ case INCOMING:
+ if (digitalRead(PIN_HANGUP) == LOW) {
+ Serial.println("SPEAKING: Picked up");
+ fona.pickUp();
+ adv_state = SPEAKING;
+ }
+ break;
+
+ case SPEAKING:
+ if (digitalRead(PIN_HANGUP) == HIGH) {
+ Serial.println("IDLE: Hung up");
+ fona.hangUp();
+ adv_state = IDLE;
+ enableGSMBusy(false);
+ }
+ break;
+
+ case WAIT_FOR_NUMBER:
+ case DIALING:
+ case BUSY:
+ if (digitalRead(PIN_HANGUP) == HIGH) {
+ MsTimer2::stop();
+ Serial.println("IDLE: Hang up abort");
+ delete_number();
+ play_dial_tone(false);
+ enableGSMBusy(false);
+ adv_state = IDLE;
+ }
+ break;
+
+ }
}
void process_input_digit() {
- switch (adv_state) {
- case WAIT_FOR_NUMBER:
- if (digit_dialed) {
- if (digit > 0 && number_len < NUMBER_LEN) {
- Serial.print("d = ");
- char d = (digit % 10) + 48;
- Serial.println(d);
- number[number_len] = d;
- fona.playDTMF(d);
- number_len++;
- }
-
- digit = 0;
- digit_dialed = 0;
- }
-
- break;
- default:
- digit = 0;
- digit_dialed = 0;
-
- break;
- }
+ switch (adv_state) {
+ case WAIT_FOR_NUMBER:
+ if (digit_dialed) {
+ if (digit > 0 && number_len < NUMBER_LEN) {
+ char d = (digit % 10) + 48;
+ number[number_len] = d;
+ number_len++;
+
+ play_dial_tone(false);
+ delay(50);
+ fona.playDTMF(d);
+ digit_playing = millis();
+ }
+
+ digit = 0;
+ digit_dialed = 0;
+ }
+ break;
+
+ default:
+ digit = 0;
+ digit_dialed = 0;
+ break;
+ }
}
void process_input_number() {
- switch (adv_state) {
- case WAIT_FOR_NUMBER:
- if (number_dialed) {
- adv_state = DIALING;
- if (call_current_number(number, &number_len)) {
- adv_state = SPEAKING;
- } else {
- delete_number();
- adv_state = IDLE;
- }
- number_dialed = 0;
- }
-
- break;
- }
+ switch (adv_state) {
+ case WAIT_FOR_NUMBER:
+ if (number_dialed) {
+ Serial.println("DIALING: number dialed");
+ adv_state = DIALING;
+ if (call_current_number(number, &number_len)) {
+ Serial.println("SPEAKING: Calling");
+ adv_state = SPEAKING;
+ } else {
+ Serial.println("IDLE: Call failed");
+ adv_state = IDLE;
+ }
+ delete_number();
+ number_dialed = 0;
+ }
+ break;
+
+ default:
+ number_dialed = 0;
+ number_len = 0;
+ break;
+ }
}
void process_output_bell() {
- static unsigned long inc_time = 0;
+ static unsigned long inc_time = 0;
- if (adv_state == INCOMING) {
- if (inc_time == 0) {
- inc_time = millis();
- }
+ if (adv_state == INCOMING) {
+ if (inc_time == 0) {
+ inc_time = millis();
+ }
+
+ int p = ((millis() - inc_time) / 1000) % 5;
+ if (p > 0){
+ digitalWrite(PIN_LED, LOW);
- int p = ((millis() - inc_time) / 1000) % 5;
- if (p > 0){
- digitalWrite(PIN_LED, LOW);
+ digitalWrite(PIN_A_BELL, LOW);
+ digitalWrite(PIN_B_BELL, LOW);
+ } else {
+ digitalWrite(PIN_LED, HIGH);
- digitalWrite(PIN_A_BELL, LOW);
- digitalWrite(PIN_B_BELL, LOW);
+ p = (millis() / RINGING_PERIOD) % 2;
+ digitalWrite(PIN_A_BELL, !p);
+ digitalWrite(PIN_B_BELL, !!p);
+ }
} else {
- digitalWrite(PIN_LED, HIGH);
+ inc_time = 0;
+ digitalWrite(PIN_LED, LOW);
- p = (millis() / 20) % 2;
- digitalWrite(PIN_A_BELL, !p);
- digitalWrite(PIN_B_BELL, !!p);
+ digitalWrite(PIN_A_BELL, LOW);
+ digitalWrite(PIN_B_BELL, LOW);
}
- } else {
- inc_time = 0;
- digitalWrite(PIN_LED, LOW);
-
- digitalWrite(PIN_A_BELL, LOW);
- digitalWrite(PIN_B_BELL, LOW);
- }
}
void process_output_speaker() {
- switch (adv_state) {
- case WAIT_FOR_NUMBER:
- if (digit_dialing) {
- play_dial_tone(false);
- } else {
- play_dial_tone(true);
- }
- break;
-
- default:
- play_dial_tone(false);
- break;
- }
+ static unsigned long next_tone = 0;
+
+ switch (adv_state) {
+ case WAIT_FOR_NUMBER:
+ if (digit_dialing) {
+ if (digit_playing == 0) {
+ play_dial_tone(false);
+ }
+ } else {
+ if (digit_playing == 0) {
+ play_dial_tone(true);
+ } else {
+ unsigned long delta = millis() - digit_playing;
+ if (delta > 2500) {
+ play_dial_tone(true);
+ digit_playing = 0;
+ }
+ }
+ }
+ break;
+
+ default:
+ play_dial_tone(false);
+ break;
+ }
}
void play_DTMF_number(char *numberDTMF) {
- for (char i = 0 ; numberDTMF[i] != '\0'; i++) {
- fona.playDTMF(numberDTMF[i]);
- }
+ for (char i = 0 ; numberDTMF[i] != '\0'; i++) {
+ fona.playDTMF(numberDTMF[i]);
+ }
}
boolean play_dial_tone(boolean enable) {
- static boolean enabled = false;
+ static boolean enabled = false;
- if (enable != enabled) {
- enabled = enable;
- if (enable) {
- return fona.sendCheckReply(F("AT+STTONE=1,1,600000"), F("OK"));
- } else {
- return fona.sendCheckReply(F("AT+STTONE=0"), F("OK"));
+ if (enable != enabled) {
+ enabled = enable;
+ if (enable) {
+ return fona.sendCheckReply(F("AT+STTONE=1,1,600000"), F("OK"));
+ } else {
+ return fona.sendCheckReply(F("AT+STTONE=0"), F("OK"));
+ }
}
- }
}
void delete_number() {
- Serial.println("Nummer loeschen");
- memset(number, '\0', NUMBER_LEN * sizeof(char));
+ Serial.println("Nummer loeschen");
+ memset(number, '\0', NUMBER_LEN * sizeof(char));
- digit = 0;
- digit_dialed = 0;
+ digit = 0;
+ digit_dialed = 0;
- number_len = 0;
- number_dialed = 0;
+ number_len = 0;
+ number_dialed = 0;
}
boolean enableGSMBusy(boolean enable) {
- static boolean enabled = false;
+ static boolean enabled = false;
- if (enable != enabled) {
- enabled = enable;
- if (enable) {
- return fona.sendCheckReply(F("AT+GSMBUSY=1"), F("OK"));
- } else {
- return fona.sendCheckReply(F("AT+GSMBUSY=0"), F("OK"));
+ if (enable != enabled) {
+ enabled = enable;
+ if (enable) {
+ return fona.sendCheckReply(F("AT+GSMBUSY=1"), F("OK"));
+ } else {
+ return fona.sendCheckReply(F("AT+GSMBUSY=0"), F("OK"));
+ }
}
- }
}
int call_current_number(char *number, int *number_len) {
- char full[NUMBER_LEN + 6];
-
- if (number[0] == '0' && number[1] != '0') {
- sprintf(full, "%s%s", "+49", number+1);
- } else if (number[0] != '0') {
- sprintf(full, "%s%s", DEFAULT_DIAL_PREFIX, number);
- } else {
- strncpy(full, number, *number_len);
- }
-
- Serial.println("Dialing: ");
- Serial.println(full);
+ char full[NUMBER_LEN + 6];
- delete_number();
+ if (number[0] == '0' && number[1] != '0') {
+ sprintf(full, "%s%s", "+49", number+1);
+ } else if (number[0] != '0') {
+ sprintf(full, "%s%s", DEFAULT_DIAL_PREFIX, number);
+ } else {
+ strncpy(full, number, *number_len);
+ }
- //play_DTMF_number(full);
- return fona.callPhone(full);
-}
+ Serial.print("Dialing: ");
+ Serial.println(full);
-void ring_bell(unsigned long inc_time) {
- int p = ((millis() - inc_time) / 1000) % 5;
- if (p > 0){
- digitalWrite(PIN_LED, LOW);
-
- digitalWrite(PIN_A_BELL, LOW);
- digitalWrite(PIN_B_BELL, LOW);
- } else {
- p = (millis() / 20) % 2;
- digitalWrite(PIN_A_BELL, !p);
- digitalWrite(PIN_B_BELL, !!p);
- digitalWrite(PIN_LED, HIGH);
- }
+ //play_DTMF_number(full);
+ return fona.callPhone(full);
}
void sig_commit_digit() {
- digit_dialed = 1;
- digit_dialing = 0;
+ digit_dialed = 1;
+ digit_dialing = 0;
}
void sig_commit_number() {
- MsTimer2::stop();
+ MsTimer2::stop();
- number_dialed = 1;
+ number_dialed = 1;
}
void sig_digit() {
- digit_dialing = 1;
- digit++;
- digitalWrite(PIN_LED, HIGH);
- detachInterrupt(INT_DIGIT);
- MsTimer2::stop();
- MsTimer2::set(25, sig_att_digit_end);
- MsTimer2::start();
+ digit_dialing = 1;
+ digit++;
+ digitalWrite(PIN_LED, HIGH);
+ detachInterrupt(INT_DIGIT);
+ MsTimer2::stop();
+ MsTimer2::set(DEBOUNCE_DELAY, sig_att_digit_end);
+ MsTimer2::start();
}
void sig_att_digit_end() {
- MsTimer2::stop();
- attachInterrupt(INT_DIGIT, sig_digit_end, FALLING);
+ MsTimer2::stop();
+ attachInterrupt(INT_DIGIT, sig_digit_end, FALLING);
}
void sig_digit_end() {
- detachInterrupt(INT_DIGIT);
- digitalWrite(PIN_LED, LOW);
- MsTimer2::stop();
- MsTimer2::set(25, sig_att_digit);
- MsTimer2::start();
+ detachInterrupt(INT_DIGIT);
+ digitalWrite(PIN_LED, LOW);
+ MsTimer2::stop();
+ MsTimer2::set(DEBOUNCE_DELAY, sig_att_digit);
+ MsTimer2::start();
}
void sig_att_digit() {
- MsTimer2::stop();
- attachInterrupt(INT_DIGIT, sig_digit, RISING);
+ MsTimer2::stop();
+ attachInterrupt(INT_DIGIT, sig_digit, RISING);
- MsTimer2::set(4000, sig_commit_number);
- MsTimer2::start();
+ MsTimer2::set(DIAL_DELAY, sig_commit_number);
+ MsTimer2::start();
}
-// vim: sw=2
+// vim: set sw=4