Skip to content

Instantly share code, notes, and snippets.

@quadney
Forked from sjbodzo/brother.inr
Last active August 29, 2015 14:19
Show Gist options
  • Save quadney/c0516f771c42b29cba2e to your computer and use it in GitHub Desktop.
Save quadney/c0516f771c42b29cba2e to your computer and use it in GitHub Desktop.
#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