aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Mikhirev2014-10-23 22:57:51 +0400
committerDmitry Mikhirev2014-10-23 22:57:51 +0400
commit6a6d104f35b57f1dcdd966f354b2beca73310fe4 (patch)
tree4e8d8802baabdcb59713e80fd50375d1e2413fb4
parent89711b175e318ba17b9e1504382e16c88cafbeea (diff)
downloadbrainuino-6a6d104f35b57f1dcdd966f354b2beca73310fe4.tar.gz
brainuino-6a6d104f35b57f1dcdd966f354b2beca73310fe4.tar.bz2
brainuino-6a6d104f35b57f1dcdd966f354b2beca73310fe4.tar.xz
brainuino-6a6d104f35b57f1dcdd966f354b2beca73310fe4.zip
major code revision
-rw-r--r--brainuino.ino194
-rw-r--r--font.h15
-rw-r--r--game.h24
-rw-r--r--lcdprint.cpp67
-rw-r--r--lcdprint.h7
-rw-r--r--pinout.h39
-rw-r--r--utf8.cpp93
-rw-r--r--utf8.h9
8 files changed, 258 insertions, 190 deletions
diff --git a/brainuino.ino b/brainuino.ino
index 6457be1..1e33602 100644
--- a/brainuino.ino
+++ b/brainuino.ino
@@ -1,7 +1,7 @@
/*
Brainuino Aleph
- Copyright (C) 2011-2013 Dmitry Mikhirev
+ Copyright (C) 2011-2014 Dmitry Mikhirev
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
@@ -26,7 +26,6 @@
LiquidCrystal lcd(LCD4, LCD6, LCD11, LCD12, LCD13, LCD14);
-
void setup()
{
lcd.begin(16, 2);
@@ -41,7 +40,6 @@ void setup()
preSignal = 0;
}
-
void loop()
{
buttonPressed = 0;
@@ -56,18 +54,17 @@ void loop()
ask();
}
-
+// ask() - wait until start button is pressed, then run timer
+// the question should be asked at this time
void ask()
{
-// waiting while question is being asked
-
digitalWrite(GREENLAMP, LOW);
digitalWrite(REDLAMP, LOW);
#ifdef RUSSIAN
- printState("Задаётся вопрос ");
+ printState(F("Задаётся вопрос "));
#else
- printState("Asking question ");
+ printState(F("Asking question "));
#endif
while (true) {
@@ -80,16 +77,14 @@ void ask()
}
}
- // if start button is pressed
- if (digitalRead(CONTROL1) == LOW) {
+ if (digitalRead(CONTROL1) == LOW) { // start button is pressed
if (discuss(timer1) == WRONG) {
while (discuss(timer2) == WRONG) {}
}
return;
}
- // if stop button is pressed
- if (digitalRead(CONTROL2) == LOW) {
+ if (digitalRead(CONTROL2) == LOW) { // stop button is pressed
return;
}
@@ -97,17 +92,14 @@ void ask()
}
}
-
-char discuss(uint16_t timer)
-{
+// discuss() - start timer and wait for button being pressed
// here teams can discuss question or single players think themselves
-
- char reply = NOREPLY;
+answer_t discuss(uint16_t timer)
+{
+ answer_t reply = NOREPLY;
// is random delay needed here when playing with false starts? unsure...
-// time = 0;
-
// reset timer or continue count
if (timer > 0) {
time = 0;
@@ -126,9 +118,9 @@ char discuss(uint16_t timer)
printGameType();
#ifdef RUSSIAN
- printState("Отсчёт: ");
+ printState(F("Отсчёт: "));
#else
- printState("Count: ");
+ printState(F("Count: "));
#endif
while (!buttonPressed && time < (timer - preSignal) * 1000) {
@@ -166,20 +158,19 @@ char discuss(uint16_t timer)
return reply;
}
-
-char answer(uint8_t num) {
-
-// waiting while answer is given
-
+// answer() - wait while the answer is given
+// return answer correctness
+answer_t answer(uint8_t num)
+{
digitalWrite(REDLAMP, HIGH);
// if (timer2 > 0)
// timer = timer2;
printPlayer(num);
#ifdef RUSSIAN
- printState("Ответ ");
+ printState(F("Ответ "));
#else
- printState("Answer ");
+ printState(F("Answer "));
#endif
printPreciseTime();
@@ -193,33 +184,29 @@ char answer(uint8_t num) {
// if start button was pressed
if (digitalRead(CONTROL1) == LOW) {
-// digitalWrite(REDLAMP, LOW);
buttonPressed = 0;
return WRONG;
}
// if stop button was pressed
if (digitalRead(CONTROL2) == LOW) {
-// digitalWrite(REDLAMP, LOW);
- buttonPressed = 0;
- return CORRECT;
+ buttonPressed = 0;
+ return CORRECT;
}
delay(100);
}
}
-
-void falseStart(uint8_t num) {
-
-// if there is false start, show info about it during few time
-
+// falseStart() - display false start message
+void falseStart(uint8_t num)
+{
tone(SPEAKER, 1784, 1000);
digitalWrite(REDLAMP, HIGH);
#ifdef RUSSIAN
- printState(" Фальстарт ");
+ printState(F(" Фальстарт "));
#else
- printState(" False start ");
+ printState(F(" False start "));
#endif
printPlayer(num);
delay(3000);
@@ -227,75 +214,66 @@ void falseStart(uint8_t num) {
return;
}
-
-void refresh() {
-
-// displaying current timer state
-
+// refresh() - display current timer state
+void refresh()
+{
time = millis() - startTime;
printTime();
}
-
-void printState(char *state) {
-
-// displaying string in the beginning of LCD second row
-
+// printState() - display string in the beginning of LCD second row
+void printState(const char *state)
+{
lcd.setCursor(0, 1);
uprint(state, &lcd);
}
+// printState() variant getting strings stored in flash
+void printState(const __FlashStringHelper *state)
+{
+ lcd.setCursor(0, 1);
+ uprint(state, &lcd);
+}
-void printTime() {
-
-// displaying time passed after starting timer
-
- char timestr[33];
- char integer[10];
- char fractional[2];
+// printTime() - display time passed since timer was started
+void printTime()
+{
+ char s[4];
- sprintf(integer, "%u", time/1000);
- sprintf(fractional, "%u", time%1000/100);
- sprintf(timestr, "%s.%s", integer, fractional);
lcd.setCursor(8, 1);
- uprint(timestr, &lcd);
+ itoa(time/1000, s, 10);
+ uprint(s, &lcd);
+ uprint(".", &lcd);
+ itoa(time%1000/100, s, 10);
+ uprint(s, &lcd);
}
-
-void printPreciseTime() {
-
-// displaying time passed after starting timer
+// printPreciseTime() - display time passed since timer was started
// or that it was not started yet
+void printPreciseTime()
+{
+ char s[5];
- char timestr[33];
- char integer[10];
- char fractional[4];
+ lcd.setCursor(8, 1);
- // if timer was started
- if (startTime > 0) {
+ if (startTime > 0) { // timer was started
time = millis()-startTime;
- sprintf(integer, "%u", time/1000);
- sprintf(fractional, "%03u", time%1000);
- sprintf(timestr, "%s.%s", integer, fractional);
- }
- // if it was not
- else
-
+ itoa(time/1000, s, 10);
+ uprint(s, &lcd);
+ sprintf(s, ".%03u", time%1000);
+ uprint(s, &lcd);
+ } else { // timer was not started yet
#ifdef RUSSIAN
- sprintf(timestr, "досрочно");
+ uprint(F("досрочно"), &lcd);
#else
- sprintf(timestr, "prematur");
+ uprint(F("prematur"), &lcd);
#endif
-
- lcd.setCursor(8, 1);
- uprint(timestr, &lcd);
+ }
}
-
-void readButton() {
-
-// scan buttons
-
+// readButton() - scan buttons
+void readButton()
+{
if (buttonPressed > 0)
return;
if (digitalRead(BUTTON1) == LOW) {
@@ -316,11 +294,9 @@ void readButton() {
}
}
-
-void pinInit() {
-
-// Arduino I/O initialisation, needed on startup only
-
+// pinInit() - Arduino I/O initialization, needed on startup only
+void pinInit()
+{
digitalWrite(2, HIGH);
digitalWrite(3, HIGH);
digitalWrite(BUTTON1, HIGH);
@@ -336,48 +312,44 @@ void pinInit() {
attachInterrupt(0, readButton, FALLING);
}
-
-void printGameType() {
-
-// displaying game title on LCD
-
+// printGameType() - display game title on LCD
+void printGameType()
+{
lcd.setCursor(0, 0);
switch (gameType) {
case BRAIN:
#ifdef RUSSIAN
- uprint(" Брейн-ринг ", &lcd);
+ uprint(F(" Брейн-ринг "), &lcd);
#else
- uprint(" Brain-ring ", &lcd);
+ uprint(F(" Brain-ring "), &lcd);
#endif
break;
case SI:
#ifdef RUSSIAN
- uprint(" Своя игра ", &lcd);
+ uprint(F(" Своя игра "), &lcd);
#else
- uprint(" Jeopardy ", &lcd);
+ uprint(F(" Jeopardy "), &lcd);
#endif
break;
case CHGK:
#ifdef RUSSIAN
- uprint("Что? Где? Когда?", &lcd);
+ uprint(F("Что? Где? Когда?"), &lcd);
#else
- uprint("What?Where?When?", &lcd);
+ uprint(F("What?Where?When?"), &lcd);
#endif
break;
}
}
-
-void printPlayer(uint8_t num) {
-
-// displaying number of player or team
-
+// printPlayer() - display number of player or team
+void printPlayer(uint8_t num)
+{
char printstring[65];
lcd.setCursor(0, 0);
@@ -385,18 +357,18 @@ void printPlayer(uint8_t num) {
case BRAIN:
#ifdef RUSSIAN
- sprintf(printstring, "Команда %u ", num);
+ sprintf(printstring, ("Команда %u "), num);
#else
- sprintf(printstring, "Team %u ", num);
+ sprintf(printstring, ("Team %u "), num);
#endif
break;
case SI:
#ifdef RUSSIAN
- sprintf(printstring, "Игрок %u ", num);
+ sprintf(printstring, ("Игрок %u "), num);
#else
- sprintf(printstring, "Player %u ", num);
+ sprintf(printstring, ("Player %u "), num);
#endif
break;
diff --git a/font.h b/font.h
index 34271be..960424f 100644
--- a/font.h
+++ b/font.h
@@ -1,7 +1,7 @@
/*
Brainuino Aleph
- Copyright (C) 2012 Dmitry Mikhirev
+ Copyright (C) 2012, 2014 Dmitry Mikhirev
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
@@ -23,15 +23,17 @@
#include <avr/pgmspace.h>
#include "pinout.h"
+const char NOCHAR = 0xff;
+
struct charcode {
- const int32_t uni;
+ const wchar_t uni;
const char font;
};
const charcode charmap[] PROGMEM = {
+// NB: keep this array sorted by uni values
-#ifdef RUSSIAN
-// English + Russian font
+#ifdef RUSSIAN // English + Russian font
// tilde
{0x007e, 0xe9},
@@ -75,7 +77,7 @@ const charcode charmap[] PROGMEM = {
{0x03bf, 0x6f},
{0x03c0, 0xbe},
{0x03c1, 0x70},
-// cyryllic
+// cyrillic
{0x0401, 0xa2},
{0x0410, 0x41},
{0x0411, 0xa0},
@@ -161,8 +163,7 @@ const charcode charmap[] PROGMEM = {
{0x2218, 0xef},
{0x22c5, 0xdf}
-#else
-// English + Japan (katakana) font
+#else // English + Japan (katakana) font
// latin-1 supplement
{0x00a2, 0xec},
diff --git a/game.h b/game.h
index 58ba479..5706461 100644
--- a/game.h
+++ b/game.h
@@ -1,7 +1,7 @@
/*
Brainuino Aleph
- Copyright (C) 2011 Dmitry Mikhirev
+ Copyright (C) 2011, 2014 Dmitry Mikhirev
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
@@ -21,17 +21,21 @@
#define game_h
// game types
-#define BRAIN 0
-#define SI 1
-#define CHGK 2
+enum game_t {
+ BRAIN ,
+ SI,
+ CHGK,
+};
//question status
-#define CORRECT 1
-#define WRONG 0
-#define NOREPLY -1
-
-uint8_t gameType;
-uint8_t withFalseStart;
+enum answer_t {
+ CORRECT = 1,
+ WRONG = 0,
+ NOREPLY = -1,
+};
+
+game_t gameType;
+bool withFalseStart;
uint8_t timer1;
uint8_t timer2;
//uint32_t timer;
diff --git a/lcdprint.cpp b/lcdprint.cpp
index af0eaeb..c53118a 100644
--- a/lcdprint.cpp
+++ b/lcdprint.cpp
@@ -1,7 +1,7 @@
/*
Brainuino Aleph
- Copyright (C) 2011-2012 Dmitry Mikhirev
+ Copyright (C) 2011, 2012, 2014 Dmitry Mikhirev
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
@@ -21,31 +21,54 @@
#include "lcdprint.h"
#include "font.h"
-size_t uprint(char* rawstr, LiquidCrystal *lcd)
+size_t uprint(const char* rawstr, Print* out)
{
- int32_t ucode;
- int i, j;
- int numcodes = sizeof(charmap)/sizeof(charcode);
utf8 str = utf8(rawstr);
- char result[str.chars()];
-
- for (i = 0; i < str.chars(); i++) {
- ucode = str.get();
- if (ucode > 0x0000) {
- if (ucode <= 0x007d) {
- result[i] = ucode;
- } else {
- result[i] = 0xff;
- for (j = 0; (j < numcodes) && (pgm_read_dword(&charmap[j].uni) <= ucode); j++) {
- if (pgm_read_dword(&charmap[j].uni) == ucode) {
- result[i] = pgm_read_byte(&charmap[j].font);
- }
- }
- }
+ return utf8print(&str, out);
+}
+
+size_t uprint(const __FlashStringHelper* rawstr, Print* out)
+{
+ utf8 str = utf8(rawstr);
+ return utf8print(&str, out);
+}
+
+size_t utf8print(utf8* str, Print* out)
+{
+ char result[str->chars() + 1];
+ wchar_t ucode;
+ int i;
+
+ for (i = 0; i < (str->chars()); i++) {
+ ucode = str->get();
+ if (ucode != 0x0000) {
+ result[i] = codeOf(ucode);
} else {
break;
}
}
- result[i] = 0;
- return lcd->print(result);
+ result[i] = '\0';
+ return out->print(result);
+}
+
+char codeOf(wchar_t ucode)
+{
+ if (ucode > 0x0000 && ucode <= 0x007d) // ASCII symbol
+ return char(ucode);
+
+ int low, high, mid;
+
+ low = 0;
+ high = sizeof(charmap)/sizeof(charcode) - 1;
+ while (low <= high) {
+ mid = (low + high) >> 1;
+ wchar_t u = pgm_read_word(&charmap[mid].uni);
+ if (wchar_t(u) > ucode)
+ high = mid - 1;
+ else if (u < ucode)
+ low = mid + 1;
+ else
+ return pgm_read_byte(&charmap[mid].font);
+ }
+ return NOCHAR;
}
diff --git a/lcdprint.h b/lcdprint.h
index bcc95f6..63fc663 100644
--- a/lcdprint.h
+++ b/lcdprint.h
@@ -1,7 +1,7 @@
/*
Brainuino Aleph
- Copyright (C) 2011-2012 Dmitry Mikhirev
+ Copyright (C) 2011, 2012, 2014 Dmitry Mikhirev
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
@@ -22,6 +22,9 @@
#include "utf8.h"
-size_t uprint (char*, LiquidCrystal*);
+size_t uprint (const char*, Print*);
+size_t uprint(const __FlashStringHelper*, Print*);
+size_t utf8print(utf8*, Print*);
+char codeOf(wchar_t);
#endif
diff --git a/pinout.h b/pinout.h
index 02f2398..670dba5 100644
--- a/pinout.h
+++ b/pinout.h
@@ -1,7 +1,7 @@
/*
Brainuino Aleph
- Copyright (C) 2011 Dmitry Mikhirev
+ Copyright (C) 2011, 2014 Dmitry Mikhirev
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
@@ -28,13 +28,15 @@ digital pins 2 and 3 must be used for interrupts */
// undefine the following if your LCD does not support Russian font
#define RUSSIAN
+enum {
+
// digital pins connected to LCD display
-#define LCD4 7
-#define LCD6 8
-#define LCD11 9
-#define LCD12 10
-#define LCD13 11
-#define LCD14 12
+ LCD4 = 7,
+ LCD6 = 8,
+ LCD11 = 9,
+ LCD12 = 10,
+ LCD13 = 11,
+ LCD14 = 12,
/* pins 1 and 5 of LCD must be connected to GND,
pin 2 - to +5V
pin 3 - to 10K potentiometer
@@ -43,29 +45,30 @@ and GND respectively
pins 7-10 - no connection */
// digital pin connected to speaker
-#define SPEAKER 5
+ SPEAKER = 5,
// digital pin connected to LED lamp
-#define GREENLAMP 13
-#define REDLAMP 6
+ GREENLAMP = 13,
+ REDLAMP = 6,
// digital pins connected to players' buttons
-#define BUTTON1 14
-#define BUTTON2 15
-#define BUTTON3 16
-#define BUTTON4 17
+ BUTTON1 = 14,
+ BUTTON2 = 15,
+ BUTTON3 = 16,
+ BUTTON4 = 17,
// digital pins connected to control buttons
// start/OK button
-#define CONTROL1 18
+ CONTROL1 = 18,
// break/cansel button
-#define CONTROL2 19
+ CONTROL2 = 19,
// digital pin connected to encoder button
-#define ENCPUSH 20
+ ENCPUSH = 20,
// digital pin connected to encoder 'B' output
-#define ENCODERB 4
+ ENCODERB = 4,
// encoder 'A' output must be connected to Arduino D3
+};
#endif
diff --git a/utf8.cpp b/utf8.cpp
index d4e605e..e4a295e 100644
--- a/utf8.cpp
+++ b/utf8.cpp
@@ -1,7 +1,7 @@
/*
Brainuino Aleph
- Copyright (C) 2012, 2013 Dmitry Mikhirev
+ Copyright (C) 2012-2014 Dmitry Mikhirev
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
@@ -15,15 +15,16 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
+ */
#include "utf8.h"
#include <string.h>
-utf8::utf8 (char* input)
+utf8::utf8 (const char* input)
{
_bytes = strlen(input);
_string = strdup(input);
+ _string_p = NULL;
_chars = 0;
for (_index = 0; _index < _bytes; _index++) {
if ((_string[_index] & 0x80) == 0x00) {
@@ -42,25 +43,83 @@ utf8::utf8 (char* input)
_index = 0;
}
+utf8::utf8 (const __FlashStringHelper* input)
+{
+ _string_p = (char*) input;
+ _string = NULL;
+ _bytes = strlen_P(_string_p);
+ _chars = 0;
+ for (_index = 0; _index < _bytes; _index++) {
+ if ((pgm_read_byte(_string_p + _index) & 0x80) == 0x00) {
+ _chars++;
+ } else if ((pgm_read_byte(_string_p + _index) & 0x20) == 0x00) {
+ _chars++;
+ _index ++;
+ } else if ((pgm_read_byte(_string_p + _index) & 0x10) == 0x00) {
+ _chars++;
+ _index += 2;
+ } else if ((pgm_read_byte(_string_p + _index) & 0x08) == 0x00) {
+ _chars++;
+ _index += 3;
+ }
+ }
+ _index = 0;
+}
+
utf8::~utf8 ()
{
- free(_string);
+ if (_string != NULL)
+ free(_string);
}
-int32_t utf8::get()
+wchar_t utf8::get()
{
- int32_t code;
- if ((_string[_index] & 0x80) == 0) {
- code = int32_t(_string[_index]);
- _index++;
- } else if ((_string[_index] & 0x20) == 0) {
- code = int32_t(_string[_index] & 0x1f) << 6 | int32_t(_string[_index+1] & 0x3f);
- _index += 2;
- } else if ((_string[_index] & 0x10) == 0) {
- code = int32_t(_string[_index] & 0xf) << 12 | int32_t(_string[_index+1] & 0x3f) << 6 | int32_t(_string[_index+2] & 0x3f);
- _index += 3;
- } else if ((_string[_index] & 0x8) == 0) {
- code = int32_t(_string[_index] & 0x7) << 18 | int32_t(_string[_index+1] & 0x3f) << 12 | int32_t(_string[_index+2] & 0x3f) << 6 | int32_t(_string[_index+3] & 0x3f);
+ wchar_t code;
+ if (_string_p == NULL) { // string in RAM
+ if ((_string[_index] & 0x80) == 0) {
+ code = wchar_t(_string[_index]);
+ _index++;
+ } else if ((_string[_index] & 0x20) == 0) {
+ code = wchar_t(_string[_index] & 0x1f) << 6 |
+ wchar_t(_string[_index+1] & 0x3f);
+ _index += 2;
+ } else if ((_string[_index] & 0x10) == 0) {
+ code = wchar_t(_string[_index] & 0x0f) << 12 |
+ wchar_t(_string[_index+1] & 0x3f) << 6 |
+ wchar_t(_string[_index+2] & 0x3f);
+ _index += 3;
+ } else if (((_string[_index] & 0x8) == 0) && (sizeof(code) >= 3)) {
+ code = wchar_t(_string[_index] & 0x07) << 18 |
+ wchar_t(_string[_index+1] & 0x3f) << 12 |
+ wchar_t(_string[_index+2] & 0x3f) << 6 |
+ wchar_t(_string[_index+3] & 0x3f);
+ } else {
+ code = '?';
+ _index++;
+ }
+ } else { // string in flash
+ byte first = pgm_read_byte(_string_p + _index);
+ if ((first & 0x80) == 0) {
+ code = wchar_t(first);
+ _index++;
+ } else if ((first & 0x20) == 0) {
+ code = wchar_t(first & 0x1f) << 6 |
+ wchar_t(pgm_read_byte(_string_p + _index + 1) & 0x3f);
+ _index += 2;
+ } else if ((first & 0x10) == 0) {
+ code = wchar_t(first & 0x0f) << 12 |
+ wchar_t(pgm_read_byte(_string_p + _index + 1) & 0x3f) << 6 |
+ wchar_t(pgm_read_byte(_string_p + _index + 2) & 0x3f);
+ _index += 3;
+ } else if (((first & 0x8) == 0) && (sizeof(code) >= 3)) {
+ code = wchar_t(first & 0x07) << 18 |
+ wchar_t(pgm_read_byte(_string_p + _index + 1) & 0x3f) << 12 |
+ wchar_t(pgm_read_byte(_string_p + _index + 2) & 0x3f) << 6 |
+ wchar_t(pgm_read_byte(_string_p + _index + 3) & 0x3f);
+ } else {
+ code = '?';
+ _index++;
+ }
}
if (_index >= _bytes) _index = 0;
return code;
diff --git a/utf8.h b/utf8.h
index 9bab45b..213042d 100644
--- a/utf8.h
+++ b/utf8.h
@@ -1,7 +1,7 @@
/*
Brainuino Aleph
- Copyright (C) 2012, 2013 Dmitry Mikhirev
+ Copyright (C) 2012-2014 Dmitry Mikhirev
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
@@ -20,13 +20,15 @@
#ifndef utf8_h
#define utf8_h
+#include <avr/pgmspace.h>
#include "Arduino.h"
class utf8 {
public:
- utf8(char* string);
+ utf8(const char* string);
+ utf8 (const __FlashStringHelper* flashString);
~utf8(void);
- int32_t get();
+ wchar_t get();
uint16_t chars();
uint16_t bytes();
@@ -35,6 +37,7 @@ class utf8 {
uint16_t _chars;
uint16_t _bytes;
char* _string;
+ char* _string_p;
};
#endif