-
-
Save quadney/c0516f771c42b29cba2e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <SD.h> | |
File tweet_file; | |
int NUM_TWEETS = 800; | |
// Pin assignments for Arduino pins to control select lines. | |
// Note : Mux A takes lines coming from T/W into breadboard. | |
// Demux B takes line coming from Mux A and demuxes it. | |
// Demux C handles last two remaining lines not gotten by B. | |
int mux_a_s0_pin = A0; | |
int mux_a_s1_pin = A1; | |
int mux_a_s2_pin = A2; | |
int mux_b_s0_pin = A3; | |
int mux_b_s1_pin = A4; | |
int mux_b_s2_pin = A5; | |
int mux_c_s0_pin = 8; | |
int mux_enable = 9; // 4051 Mux chips are low true enabled./ | |
int kneeler_pin = 3; | |
int red_pin = 5; | |
int green_pin = 6; | |
// Note : For Demux C only need to grab T/W pins 16 & 17, so only need | |
// to use 1 line. The other 2 lines are tied to ground, meaning | |
// we only ref the 'bottom' of Demux C's addressable lines. | |
int keyDelay = 220; // Var to control ms between key presses. | |
int pin_mapping[18]; // This array stores what pin maps to what select val. | |
boolean doneTweeting = true; // Set to true once the tweet prints. | |
boolean isPrinting = false; | |
boolean isKneeling = false; | |
int kneelCount = 0; | |
int PAPER_WIDTH = 27; // For tracking when to insert new lines in string when printing from t/w. | |
int MAX_TWEET_LENGTH = 141; // Max tweet size + termination char | |
int ARR_LENGTH = MAX_TWEET_LENGTH + (MAX_TWEET_LENGTH % PAPER_WIDTH) + 1; // Total length of char array for string output to t/w. | |
int end = 0; | |
int i = 0; | |
int tweet_index = 1; | |
// Note : pin_mapping will map t/w pins to select values, which will | |
// help arduino know which pin they want to select. | |
// Example : t/w pin 17 should select line 0 to go from mux c -> t/w | |
void setup() { | |
Serial.begin(9600); // Param is which serial port to listen on. | |
init_vars(); | |
Serial.setTimeout(5); | |
// Initiate reading of sdcard on CS (pin 4) | |
if (!SD.begin(4)) { | |
Serial.println("initialization failed!"); | |
return; | |
} | |
// Assigns values for selection to t/w pins. | |
// These pins are read out from t/w and into our circuit. | |
pin_mapping[1] = 0; | |
pin_mapping[2] = 1; | |
pin_mapping[3] = 2; | |
pin_mapping[4] = 3; | |
pin_mapping[5] = 4; | |
pin_mapping[6] = 5; | |
pin_mapping[7] = 6; | |
pin_mapping[8] = 7; | |
// These pins are written back into t/w from our circuit. | |
pin_mapping[9] = 1; | |
pin_mapping[10] = 2; | |
pin_mapping[11] = 3; | |
pin_mapping[12] = 4; | |
pin_mapping[13] = 5; | |
pin_mapping[14] = 6; | |
pin_mapping[15] = 7; | |
pin_mapping[16] = 0; | |
pin_mapping[17] = 0; | |
// Note : 16 & 17 are set to 0 b/c in our circuit selecting option | |
// 0 triggers selection of those lines on Demux C. | |
// Consequently, pin 9 starts the pin count at 1. | |
} | |
void init_vars() { | |
// Assigns Arduino pins to respective functions. | |
pinMode(mux_enable , OUTPUT); | |
pinMode(mux_a_s0_pin , OUTPUT); | |
pinMode(mux_a_s1_pin , OUTPUT); | |
pinMode(mux_a_s2_pin , OUTPUT); | |
pinMode(mux_b_s0_pin , OUTPUT); | |
pinMode(mux_b_s1_pin , OUTPUT); | |
pinMode(mux_b_s2_pin , OUTPUT); | |
pinMode(mux_c_s0_pin , OUTPUT); | |
pinMode(kneeler_pin, INPUT); //TODO : incorporate kneeler | |
// green = 6 | |
// red = 5 | |
// button = 3 | |
} | |
void turnLightsOn() { | |
analogWrite(red_pin, 255); | |
analogWrite(green_pin, 56); | |
} | |
void turnLightsOff() { | |
analogWrite(red_pin, 0); | |
analogWrite(green_pin, 0); | |
} | |
void loop() { | |
init_vars(); | |
digitalWrite(mux_enable, HIGH); // Ensures chips are off. | |
isKneeling = !digitalRead(kneeler_pin); //HIGH is notKneeling, LOW is kneeling | |
if(!isKneeling) kneelCount = 0; | |
if(isKneeling) { | |
kneelCount++; | |
if(!isPrinting && kneelCount == 1) doneTweeting = false; | |
} | |
if (!doneTweeting) { // Low true signal says somebody is kneeling | |
// Send a request to the computer for a tweet | |
isPrinting = true; | |
turnLightsOn(); // Switch lights to yellow | |
char twit[ARR_LENGTH]; | |
fetchTweet(tweet_index++, twit); | |
String phrase = twit; | |
Serial.println(twit); | |
int p; | |
for(p=0; phrase.charAt(p)!='\0'; ++p); | |
parse_for_tw(twit, p+5, phrase); | |
if (tweet_index >= NUM_TWEETS) tweet_index = 0; | |
//delay(2000); | |
digitalWrite(mux_enable, LOW); | |
pressKey(8,10); // Re-aligns printhead in case of prior error | |
digitalWrite(mux_enable, HIGH); | |
printString(twit); | |
doneTweeting = true; | |
//debug_str(); | |
//debug_tw_pins(); | |
} | |
} | |
void fetchTweet(int index, char* s) { | |
// Open tweets file and find requested tweet | |
tweet_file = SD.open("/tweets.txt", FILE_READ); | |
int i = 0; // Counter to track current tweet index | |
if (tweet_file) { | |
char byte_in; | |
while (tweet_file.available()) { | |
byte_in = tweet_file.read(); | |
if (byte_in == '\n') { | |
i++; | |
// Check if this is the tweet we want and add to it | |
if (i == index) { break; } | |
} | |
} | |
// Now grab the tweet off the line char by char | |
byte_in = tweet_file.read(); | |
int k = 0; | |
while (byte_in != '\n') { | |
if ((byte_in < 123 && byte_in > 96) || (byte_in == 46) || (byte_in == 32)) s[k++] = byte_in; | |
byte_in = tweet_file.read(); | |
} | |
Serial.println("DONE"); | |
s[k++] = '/0'; | |
tweet_file.close(); | |
} | |
} | |
void get_spaces(String s, int* spaces, int l) { | |
// Serial.print("Spaces: "); | |
for (int i = 0; i < l; i++) { | |
if (s.charAt(i) == ' ') spaces[i] = 1; | |
else spaces[i] = 0; | |
// Serial.print(spaces[i]); | |
} | |
// Serial.println(); | |
// Serial.print("String: "); | |
for (int i = 0; i < l && s.charAt(i) != '\0'; i++) { | |
// Serial.print(s.charAt(i)); | |
} | |
// Serial.println(); | |
} | |
void parse_for_tw(char* str_arr, int l, String s) { | |
// Serial.print("Size of string: "); | |
// Serial.println(l); | |
int spaces[l]; | |
get_spaces(s, spaces, l); | |
int col = 0; | |
int index_ctr = 0; | |
int x = 0; | |
for (; x < l; x++) { | |
if (index_ctr == l) break; // End of string | |
else if (index_ctr == l-1) { str_arr[x] = '\n'; } | |
else if (col >= PAPER_WIDTH/2) { | |
int sp_index = index_ctr+1; | |
while (spaces[sp_index] != 1 && s.charAt(sp_index) != '\n' && s.charAt(sp_index) != '\0') { | |
sp_index++; | |
} | |
if (sp_index/PAPER_WIDTH > (index_ctr-4)/PAPER_WIDTH) { // If next space is too far to the right, start new line | |
// Serial.println(); | |
// Serial.print(sp_index); | |
// Serial.print(" "); | |
// Serial.println(PAPER_WIDTH); | |
str_arr[x] = '\n'; | |
col = 0; | |
} | |
else { | |
str_arr[x] = s.charAt(index_ctr++); | |
col++; | |
} | |
} | |
else if (col == PAPER_WIDTH) { | |
str_arr[x] = '\n'; | |
col = 0; | |
} | |
else { | |
str_arr[x] = s.charAt(index_ctr++); | |
col++; | |
} | |
} | |
str_arr[x++] = '\n'; | |
str_arr[x] = '\0'; | |
end = x; | |
// Serial.print("index of termination = "); | |
// Serial.println(x); | |
} | |
void debug_str() { | |
int index = 0; | |
char twit[10]; | |
twit[0] = 'i'; | |
twit[1] = 'm'; | |
twit[2] = ' '; | |
twit[3] = 's'; | |
twit[4] = 'o'; | |
twit[5] = 'r'; | |
twit[6] = 'r'; | |
twit[7] = 'y'; | |
twit[8] = '\n'; | |
twit[9] = '\0'; | |
printString(twit); | |
} | |
// Pass a t/w pin for from and to the t/w, and test that pin combo. | |
void debug_tw_pins() { | |
int out_to_tw_pin = Serial.parseInt(); | |
int in_from_tw_pin = Serial.parseInt(); | |
if (Serial.read() == '\n') { | |
if (out_to_tw_pin > 17 || out_to_tw_pin < 9) { | |
// Serial.println("Error: That pin doesn't go back into the t/w!"); | |
return; | |
} | |
if (in_from_tw_pin > 8 || in_from_tw_pin < 1) { | |
// Serial.println("Error: That pin doesn't come from the t/w!"); | |
return; | |
} | |
digitalWrite(mux_enable, LOW); // Turns on the mux chips. | |
pressKey(in_from_tw_pin, out_to_tw_pin); | |
digitalWrite(mux_enable, HIGH); // Turns off mux chips. | |
} | |
} | |
void debug_char() { | |
int index = 0; | |
String input; | |
delay(500); | |
while (Serial.available()) { | |
if (index > 0) break; | |
input.concat(Serial.readString()); | |
index++; | |
} | |
digitalWrite(mux_enable, LOW); // Turns on mux chip. | |
getChar(input[0]); | |
digitalWrite(mux_enable, HIGH); // Turns off mux chip. | |
} | |
void pressKey(int in_from_tw_pin, int out_to_tw_pin) { | |
setKey(in_from_tw_pin, out_to_tw_pin); | |
delay(keyDelay); | |
} | |
void setKey(int in_from_tw_pin, int out_to_tw_pin) { | |
int shifted_val; | |
int mux_a_select_nibble = pin_mapping[in_from_tw_pin]; | |
int mux_b_select_nibble = pin_mapping[out_to_tw_pin]; | |
//Debug print information to help with understand how circuit is working. | |
// Serial.println("\n"); | |
// Serial.println("------------------------------------------"); | |
// Serial.print("| Reading from t/w pin #"); | |
// Serial.println(in_from_tw_pin); | |
// Serial.print("| Connecting to t/w pin #"); | |
// Serial.println(out_to_tw_pin); | |
//Create string vars to store values of select lines for printing. | |
String msa = ""; | |
String msb = ""; | |
String msc = ""; | |
// Set select to know which line we want to grab from the t/w and | |
// run through our circuit via Mux A. | |
shifted_val = (mux_a_select_nibble & B100) >> 2; | |
digitalWrite(mux_a_s2_pin, shifted_val); | |
msa.concat(shifted_val); | |
shifted_val = (mux_a_select_nibble & B010) >> 1; | |
digitalWrite(mux_a_s1_pin, shifted_val); | |
msa.concat(shifted_val); | |
shifted_val = (mux_a_select_nibble & B001); | |
digitalWrite(mux_a_s0_pin, shifted_val); | |
msa.concat(shifted_val); | |
// Set select to know which line we want to output from Demux B. | |
// Output of T/W lines 9-15 are chosen here. (Lines 16 & 17 are | |
// handled by the 2nd demux, which we call Demux C and handle next.) | |
shifted_val = (mux_b_select_nibble & B100) >> 2; | |
digitalWrite(mux_b_s2_pin, shifted_val); | |
msb.concat(shifted_val); | |
shifted_val = (mux_b_select_nibble & B010) >> 1; | |
digitalWrite(mux_b_s1_pin, shifted_val); | |
msb.concat(shifted_val); | |
shifted_val = (mux_b_select_nibble & B001); | |
digitalWrite(mux_b_s0_pin, shifted_val); | |
msb.concat(shifted_val); | |
// Set select to choose between T/W lines 16 & 17 on Demux C. | |
// (This happens if Demux B selects line 000). | |
if (out_to_tw_pin == 16) { | |
digitalWrite(mux_c_s0_pin, 0); | |
msc.concat(0); | |
} | |
else if (out_to_tw_pin == 17) { | |
digitalWrite(mux_c_s0_pin, 1); | |
msc.concat(1); | |
} | |
else { | |
msc.concat('X'); | |
} | |
//Print out values of select lines. | |
// Serial.println("| MSA: " + msa + "\tMSB: " + msb + "\tMSC: " + msc + "\n"); | |
} | |
void getChar(char letter){ | |
switch(letter) { | |
case 'A': | |
pushCaps(); | |
pressKey(9,2); | |
pushCaps(); | |
break; | |
case 'a': | |
pressKey(9,2); | |
break; | |
case 'B': | |
pushCaps(); | |
pressKey(10,7); | |
pushCaps(); | |
break; | |
case 'b': | |
pressKey(10,7); | |
break; | |
case 'C': | |
pushCaps(); | |
pressKey(2,11); | |
pushCaps(); | |
break; | |
case 'c': | |
pressKey(2,11); | |
break; | |
case 'D': | |
pushCaps(); | |
pressKey(5,11); | |
pushCaps(); | |
break; | |
case 'd': | |
pressKey(5,11); | |
break; | |
case 'E': | |
pushCaps(); | |
pressKey(6,11); | |
pushCaps(); | |
break; | |
case 'e': | |
pressKey(6,11); | |
break; | |
case 'F': | |
pushCaps(); | |
pressKey(5,16); | |
pushCaps(); | |
break; | |
case 'f': | |
pressKey(5,16); | |
break; | |
case 'G': | |
pushCaps(); | |
pressKey(2,16); | |
pushCaps(); | |
break; | |
case 'g': | |
pressKey(2,16); | |
break; | |
case 'H': | |
pushCaps(); | |
pressKey(6,14); | |
pushCaps(); | |
break; | |
case 'h': | |
pressKey(6,14); | |
break; | |
case 'I': | |
pushCaps(); | |
pressKey(7,15); | |
pushCaps(); | |
break; | |
case 'i': | |
pressKey(7,15); | |
break; | |
case 'J': | |
pushCaps(); | |
pressKey(5,14); | |
pushCaps(); | |
break; | |
case 'j': | |
pressKey(5,14); | |
break; | |
case 'K': | |
pushCaps(); | |
pressKey(5,15); | |
pushCaps(); | |
break; | |
case 'k': | |
pressKey(5,15); | |
break; | |
case 'L': | |
pushCaps(); | |
pressKey(2,15); | |
pushCaps(); | |
break; | |
case 'l': | |
pressKey(2,15); | |
break; | |
case 'M': | |
pushCaps(); | |
pressKey(3,15); | |
pushCaps(); | |
break; | |
case 'm': | |
pressKey(3,15); | |
break; | |
case 'N': | |
pushCaps(); | |
pressKey(2,14); | |
pushCaps(); | |
break; | |
case 'n': | |
pressKey(2,14); | |
break; | |
case 'O': | |
pushCaps(); | |
pressKey(7,12); | |
pushCaps(); | |
break; | |
case 'o': | |
pressKey(7,12); | |
break; | |
case 'P': | |
pushCaps(); | |
pressKey(5,12); | |
pushCaps(); | |
break; | |
case 'p': | |
pressKey(5,12); | |
break; | |
case 'Q': | |
pushCaps(); | |
pressKey(7,9); | |
pushCaps(); | |
break; | |
case 'q': | |
pressKey(7,9); | |
break; | |
case 'R': | |
pushCaps(); | |
pressKey(6,16); | |
pushCaps(); | |
break; | |
case 'r': | |
pressKey(6,16); | |
break; | |
case 'S': | |
pushCaps(); | |
pressKey(5,9); | |
pushCaps(); | |
break; | |
case 's': | |
pressKey(5,9); | |
break; | |
case 'T': | |
pushCaps(); | |
pressKey(7,16); | |
pushCaps(); | |
break; | |
case 't': | |
pressKey(7,16); | |
break; | |
case 'U': | |
pushCaps(); | |
pressKey(6,15); | |
pushCaps(); | |
break; | |
case 'u': | |
pressKey(6,15); | |
break; | |
case 'V': | |
pushCaps(); | |
pressKey(3,16); | |
pushCaps(); | |
break; | |
case 'v': | |
pressKey(3,16); | |
break; | |
case 'W': | |
pushCaps(); | |
pressKey(7,11); | |
pushCaps(); | |
break; | |
case 'w': | |
pressKey(7,11); | |
break; | |
case 'X': | |
pushCaps(); | |
pressKey(3,11); | |
pushCaps(); | |
break; | |
case 'x': | |
pressKey(3,11); | |
break; | |
case 'Y': | |
pushCaps(); | |
pressKey(7,14); | |
pushCaps(); | |
break; | |
case 'y': | |
pressKey(7,14); | |
break; | |
case 'Z': | |
pushCaps(); | |
pressKey(3,9); | |
pushCaps(); | |
break; | |
case 'z': | |
pressKey(3,9); | |
break; | |
case '1': | |
pressKey(8,9); | |
break; | |
case '!': //UNKNOWN | |
pushCaps(); | |
pressKey(5,6); | |
pushCaps(); | |
break; | |
case '2': | |
pressKey(8,11); | |
break; | |
case '@': | |
pushCaps(); | |
pressKey(5,5); | |
pushCaps(); | |
break; | |
case '3': | |
pressKey(8,16); | |
break; | |
case '#': | |
pushCaps(); | |
pressKey(5,4); | |
pushCaps(); | |
break; | |
case '4': | |
pressKey(8,14); | |
break; | |
case '$': | |
pushCaps(); | |
pressKey(8,14); | |
pushCaps(); | |
break; | |
case '5': | |
pressKey(6,10); | |
break; | |
case '%': | |
pushCaps(); | |
pressKey(5,2); | |
pushCaps(); | |
break; | |
case '6': | |
pressKey(3,14); | |
break; | |
case '7': | |
pressKey(5,10); | |
break; | |
case '&': | |
pushCaps(); | |
pressKey(7,7); | |
pushCaps(); | |
break; | |
case '8': | |
pressKey(8,15); | |
break; | |
case '*': | |
pushCaps(); | |
pressKey(7,6); | |
pushCaps(); | |
break; | |
case '9': | |
pressKey(8,12); | |
break; | |
case '(': | |
pushCaps(); | |
pressKey(8,12); | |
pushCaps(); | |
break; | |
case '0': | |
pressKey(8,13); | |
break; | |
case ')': | |
pushCaps(); | |
pressKey(8,13); | |
pushCaps(); | |
break; | |
case '.': | |
pressKey(4,15); | |
break; | |
case ';': | |
pressKey(12,4); | |
break; | |
case ':': | |
pushCaps(); | |
pressKey(6,5); | |
pushCaps(); | |
break; | |
case '?': | |
pushCaps(); | |
pressKey(4,13); | |
pushCaps(); | |
break; | |
case '\'': | |
pressKey(8,15); | |
break; | |
case ' ': | |
pressKey(4,17); | |
break; | |
case '/': | |
pressKey(8,16); | |
break; | |
case '-': | |
pressKey(7,13); | |
break; | |
case '\n': | |
pressEnter(); | |
break; | |
case ',': | |
pressKey(12,2); | |
break; | |
case '[': | |
pressKey(4,13); | |
break; | |
case ']': | |
pressKey(1,12); | |
break; | |
default: // If we have some weird unicode character, just input a space | |
pressKey(4,17); | |
break; | |
} | |
} | |
void pushCaps(){ | |
pressKey(4,16); | |
} | |
void pressEnter(){ | |
pressKey(8,10); | |
// Serial.print('\n'); | |
} | |
void goUp() { | |
pressKey(1,15); | |
} | |
void goDown() { | |
pressKey(1,16); | |
} | |
void goRight() { | |
pressKey(4,17); | |
} | |
void putafourth() { | |
pressKey(3,13); | |
} | |
void pressDash(){ | |
pressKey(7,3); | |
// Serial.print('\n'); | |
} | |
void pressKey(char key){ | |
getChar(key); | |
} | |
void printString(char* tweet){ | |
for(int i = 0; i < end+1; i++){ | |
// Serial.print("PRINTING "); | |
// Serial.println(tweet[i]); | |
if(tweet[i] == '\0') { | |
// Serial.println("FOUND IT"); | |
break; | |
} | |
// Ensure that we don't try to type a key that will bust the typewriter (ASCII) | |
if (tweet[i] > 122 || tweet[i] < 97) { // If it isn't an alpha key | |
if (tweet[i] != 32) { // If it isn't a space | |
if (tweet[i] != 10) { // If it isn't a NL (carriage return) | |
tweet[i] = ' '; | |
} | |
} | |
} | |
digitalWrite(mux_enable, LOW); // Ensures chips are ON. | |
pressKey(tweet[i]); | |
digitalWrite(mux_enable, HIGH); // Ensures chips are off. | |
delay(100); | |
} | |
digitalWrite(mux_enable, LOW); | |
pressKey(8,10); | |
pressKey(8,10); | |
pressKey(8,10); | |
pressKey(8,10); | |
pressKey(8,10); | |
pressKey(8,10); | |
digitalWrite(mux_enable, HIGH); | |
doneTweeting = true; | |
turnLightsOff(); | |
isPrinting = false; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment