AGS : Haiku Shake V01

img_0665.jpg

AGS aka Haiku Shake is a haiku generator. Tilting to the left begins the trickling of the haiku. Each haiku is generated randomly based on 3 haiku forms and a set of preselected words. To generate a new haiku, just shake it.



AGS : HaikuShake V01 from che-wei wang on Vimeo.
Verson 01 features:
-tiny word set (to be expanded)
-uses flash memory to store words (PROGMEM)
-syllable checking for haiku form
-single haiku form (to be expanded to 3)
-simple article choosing function between ‘a’ or ‘an’
-trickling text based on tilt
-shake sensor to generate a new haiku

Arduino Code

//AGS:HaikuShake V01
/*
haiku:
 form1:
 article adjective noun
 article noun verb preposition article noun
 adjective adjective noun

 form2:
 noun preposition article noun
 article adjective noun preposition article noun
 adjective noun

 form3:
 article adjective adjective noun
 preposition article adjective noun
 article noun verb
 */

//hardware connections
/*
 tiltX to analog 0
 tiltY to analog 1
 LCD power to digital 2
 LCD rx to tx (digital 1)
 */

#include <avr>//for PROGMEM

////////////////////////////////////////////////////

//nouns
prog_char noun_0[] PROGMEM = "breeze ";
prog_char noun_1[] PROGMEM = "moon ";
prog_char noun_2[] PROGMEM = "rain ";
prog_char noun_3[] PROGMEM = "wind ";
prog_char noun_4[] PROGMEM = "sea ";
prog_char noun_5[] PROGMEM = "sky ";
prog_char noun_6[] PROGMEM = "storm ";
prog_char noun_7[] PROGMEM = "water ";
prog_char noun_8[] PROGMEM = "finger ";
prog_char noun_9[] PROGMEM = "sandwich ";
prog_char noun_10[] PROGMEM = "monkey ";

prog_char noun_11[] PROGMEM = "tree ";
prog_char noun_12[] PROGMEM = "wind ";
prog_char noun_13[] PROGMEM = "peace ";
prog_char noun_14[] PROGMEM = "love ";
prog_char noun_15[] PROGMEM = "clock ";
prog_char noun_16[] PROGMEM = "grapefruit ";
prog_char noun_17[] PROGMEM = "cloud ";
prog_char noun_18[] PROGMEM = "ocean ";
prog_char noun_19[] PROGMEM = "fog ";
prog_char noun_20[] PROGMEM = "wave ";

prog_char noun_21[] PROGMEM = "treasure ";
prog_char noun_22[] PROGMEM = "island ";
prog_char noun_23[] PROGMEM = "harmony ";
prog_char noun_24[] PROGMEM = "speaker ";
prog_char noun_25[] PROGMEM = "care ";
prog_char noun_26[] PROGMEM = "trail ";
prog_char noun_27[] PROGMEM = "twinkle ";
prog_char noun_28[] PROGMEM = "flower ";
prog_char noun_29[] PROGMEM = "forrest ";

int nounSyllables[]={
  1,1,1,1,1,1,1,2,2,2,2,
  1,1,1,1,1,2,1,2,1,1,
  2,2,3,2,1,1,2,2,2
};

int nounLength=30;
PGM_P PROGMEM noun_table[]={
  noun_0, noun_1,noun_2, noun_3, noun_4, noun_5, noun_6, noun_7, noun_8, noun_9, noun_10,
  noun_11,noun_12, noun_13, noun_14, noun_15, noun_16, noun_17, noun_18, noun_19, noun_20,
  noun_21,noun_22, noun_23, noun_24, noun_25, noun_26, noun_27, noun_28, noun_29};

//adjectives
prog_char adj_0[] PROGMEM = "liquid ";
prog_char adj_1[] PROGMEM = "gusty ";
prog_char adj_2[] PROGMEM = "flowing ";
prog_char adj_3[] PROGMEM = "brutal ";
prog_char adj_4[] PROGMEM = "hidden ";
prog_char adj_5[] PROGMEM = "bitter ";
prog_char adj_6[] PROGMEM = "misty ";
prog_char adj_7[] PROGMEM = "simple ";
prog_char adj_8[] PROGMEM = "cute ";
prog_char adj_9[] PROGMEM = "adorable ";
prog_char adj_10[] PROGMEM = "pretty ";

prog_char adj_11[] PROGMEM = "perfect ";
prog_char adj_12[] PROGMEM = "white ";
prog_char adj_13[] PROGMEM = "shiny ";
prog_char adj_14[] PROGMEM = "blue ";

int adjSyllables[]={
  2,2,2,2,2,2,2,2,1,4,2,
  2,1,2,1};
int adjLength=15;
PGM_P PROGMEM adj_table[]={
  adj_0, adj_1, adj_2, adj_3, adj_4,  adj_5, adj_6, adj_7,adj_8,adj_9 ,adj_10,
  adj_11, adj_12, adj_13, adj_14 };

//verbs
prog_char verb_0[] PROGMEM = "shakes ";
prog_char verb_1[] PROGMEM = "drifts ";
prog_char verb_2[] PROGMEM = "has stopped ";
prog_char verb_3[] PROGMEM = "struggles ";
prog_char verb_4[] PROGMEM = "whispers ";
prog_char verb_5[] PROGMEM = "grows ";
prog_char verb_6[] PROGMEM = "flies ";
prog_char verb_7[] PROGMEM = "rips ";
prog_char verb_8[] PROGMEM = "shears ";
prog_char verb_9[] PROGMEM = "hugs ";
prog_char verb_10[] PROGMEM = "kisses ";

prog_char verb_11[] PROGMEM = "touches ";
prog_char verb_12[] PROGMEM = "skips ";
prog_char verb_13[] PROGMEM = "hops ";
prog_char verb_14[] PROGMEM = "smiles ";

int verbSyllables[]={
  1,1,2,2,2,1,1,1,1,1,2,
  2,1,1,1};
int verbLength=15;
PGM_P PROGMEM verb_table[]={
  verb_0,verb_1,verb_2,verb_3,verb_4,verb_5,verb_6,verb_7,verb_8,verb_9,verb_10,
  verb_11,verb_12,verb_13,verb_14 };

//articles
prog_char art_0[] PROGMEM = "a ";
prog_char art_1[] PROGMEM = "an ";
prog_char art_2[] PROGMEM = "this ";
prog_char art_3[] PROGMEM = "that ";
prog_char art_4[] PROGMEM = "either ";
prog_char art_5[] PROGMEM = "which ";
prog_char art_6[] PROGMEM = "the ";
int artSyllables[]={
  1,1,1,1,2,1};
int artLength=6;
PGM_P PROGMEM art_table[]={
  art_0,art_1,art_2,art_3,art_4,art_5,art_6};

//prepositions
prog_char prep_0[] PROGMEM = "of ";
prog_char prep_1[] PROGMEM = "to ";
prog_char prep_2[] PROGMEM = "in ";
prog_char prep_3[] PROGMEM = "for ";
prog_char prep_4[] PROGMEM = "on ";
prog_char prep_5[] PROGMEM = "from ";
prog_char prep_6[] PROGMEM = "with ";
prog_char prep_7[] PROGMEM = "as ";
prog_char prep_8[] PROGMEM = "by ";

int prepSyllables[]={
  1,1,1,1,1,1,1,1,1};
int prepLength=9;
PGM_P PROGMEM prep_table[]={
  prep_0,prep_1,prep_2,prep_3,prep_4,prep_5,prep_6,prep_7,prep_8};

////////////////////////////////////////////////////

// make sure this is large enough for the largest string it must hold
char bufferA[15];
char bufferB[15];
char bufferC[15];
char bufferD[15];
char bufferE[15];
char bufferF[15];
char bufferG[15];
char bufferH[15];
char bufferI[15];
char bufferJ[15];
char bufferK[15];
char bufferL[15]; 

int form=0;

int r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12; //random numbers
int line0Total,line1Total,line2Total=0; //haiku syllable line totals

boolean home=false; //go to top of program
boolean newForm=true;
int scrollCount=0;

//tilt
int x0, y0, x, y;
boolean zero=false;
long resTimer=0; //sensor timer
long tiltTimer=0;
boolean shaken=false;

void clearBuffers(){
  for( int i=0;i&lt;15;i++){
    bufferA[i]=NULL;
    bufferB[i]=NULL;
    bufferC[i]=NULL;
    bufferD[i]=NULL;
    bufferE[i]=NULL;
    bufferF[i]=NULL;
    bufferG[i]=NULL;
    bufferH[i]=NULL;
    bufferI[i]=NULL;
    bufferJ[i]=NULL;
    bufferK[i]=NULL;
    bufferL[i]=NULL;
  }
}

void reset(){
  clearLCD();
  //set display brightness
  Serial.print(124,BYTE);//command header
  Serial.print(129,BYTE);//display brightness 129-
  //while( checkShake() )delay(100);
  //reset line totals
  line0Total=0;
  line1Total=0;
  line2Total=0;
  clearBuffers();
  newForm=true;
  home=true;
  delay(100);
}

void setup(){
  pinMode(2,OUTPUT);
  Serial.begin(9600);
  //splash toggle
  //Serial.print(124,BYTE);//command header
  //Serial.print(9,BYTE);//toggle splash
}

void formBuffer(int form, int line){
  if(form==0){
    int lineTotal=0;

    //reset buffers
    //generate random values to select words
    if(line==0){
      while (lineTotal!=5){//continue random selection until syllable total is 5
        //article adjective noun
        int ra=getRandom(artLength) ;
        int rb=getRandom(adjLength);
        int rc=getRandom(nounLength);
        strcpy_P(bufferA, (char*)pgm_read_word(&amp;(art_table[ra] ))); // Necessary casts and dereferencing, just copy.
        strcpy_P(bufferB, (char*)pgm_read_word(&amp;(adj_table[rb] )));
        strcpy_P(bufferC, (char*)pgm_read_word(&amp;(noun_table[rc] )));
        switchArticle(bufferA,bufferB);
        //check syllable count
        lineTotal=artSyllables[ra]+adjSyllables[rb]+nounSyllables[rc];
      }
    }

    else if(line==1){
      while (lineTotal!=7){//continue random selection until syllable total is 5
        //article noun verb preposition article noun
        int ra=getRandom(artLength) ;
        int rb=getRandom(nounLength);
        int rc=getRandom(verbLength);
        int rd=getRandom(prepLength) ;
        int re=getRandom(artLength);
        int rf=getRandom(nounLength);
        strcpy_P(bufferD, (char*)pgm_read_word(&amp;(art_table[ra] )));
        strcpy_P(bufferE, (char*)pgm_read_word(&amp;(noun_table[rb] )));
        strcpy_P(bufferF, (char*)pgm_read_word(&amp;(verb_table[rc] )));
        strcpy_P(bufferG, (char*)pgm_read_word(&amp;(prep_table[rd] )));
        strcpy_P(bufferH, (char*)pgm_read_word(&amp;(art_table[re] )));
        strcpy_P(bufferI, (char*)pgm_read_word(&amp;(noun_table[rf] )));
        switchArticle(bufferD,bufferE);
        switchArticle(bufferH,bufferI);
        lineTotal=artSyllables[ra]+nounSyllables[rb]+verbSyllables[rc]+prepSyllables[rd]+artSyllables[re]+nounSyllables[rf];
      }
    }

    else if(line==2){
      while (lineTotal!=5){//continue random selection until syllable total is 5
        //adjective adjective noun
        int ra=getRandom(adjLength) ;
        int rb=getRandom(adjLength);
        int rc=getRandom(nounLength);

        strcpy_P(bufferJ, (char*)pgm_read_word(&amp;(adj_table[ra] )));
        strcpy_P(bufferK, (char*)pgm_read_word(&amp;(adj_table[rb] )));
        strcpy_P(bufferL, (char*)pgm_read_word(&amp;(noun_table[rc] )));

        switchArticle(bufferK,bufferL);
        lineTotal=adjSyllables[ra]+adjSyllables[rb]+nounSyllables[rc];
      }
    }
  }

}

int getRandom( int length ){
  delay(15);
  randomSeed(analogRead(5));
  return random(length);
}

int printBuffer(int pos, char* buffer){
  int j=0;
  int cursor;
  //print each character from buffer while not NULL
  while(buffer[j]!=NULL){
    cursor=pos+j;

    //trickle left text
    int k;
    if(tiltLeft()){
      if(cursor&lt;64)k=15-cursor;
      else if(cursor&gt;=64)k=78-cursor;
      while(cursor+k&gt;=cursor){
        k--;
        cursorPos(cursor+k+1);
        Serial.print( buffer[j]);
        delay(constrain(55+x,1,60));
        cursorPos(cursor+k+1);
        Serial.print(' ');
      }
      cursorPos(cursor);
      Serial.print( buffer[j] );
      j++;
    }

    else if (tiltRight() &amp;&amp; j&gt;0){
      k=-1;
      while(cursor&lt;64 &amp;&amp; cursor+k&lt;=15 || cursor&gt;=64 &amp;&amp; cursor+k&lt;=79+scrollCount){
        k++;
        cursorPos(cursor+k-1);
        Serial.print( buffer[j-1]);
        delay(constrain(55-x,1,60));
        cursorPos(cursor+k-1);
        Serial.print(' ');
      }
      j--;
      if(j&lt;0)j=0;
    }

    //scroll if text runs off
    if(cursor&gt;16 &amp;&amp; cursor&lt;64){
      scrollL();
      scrollCount++;
    }

    if( cursor&gt;80+scrollCount ) scrollL();

    //pause if flat
    while(tiltLeft()==false &amp;&amp; tiltRight()==false){
      delay(5);
      if(checkShake()){
        reset();
        break;
      }
    }
    if(checkShake()){
      reset();
      break;
    }

  }

  //pause after each word
  long t=millis();
  while(millis()-t<j*10.0){>
    if( checkShake() )reset();
  }
  return cursor+1;
}

void loop(){

  home=false; //at the top of the page

    long t;
  // zero tilt sensor
  if(zero==false){
    delay(300);
    setZero();
    reset();
    splash();
  }

  //LINE00///////////////////////////////////////////

  if(newForm==true){
    formBuffer(0,0);
    formBuffer(0,1);
    formBuffer(0,2);
    newForm=false;
  }

  while(home==false){
    fadeIn();
    int cursor=0;
    cursor=printBuffer(cursor,bufferA);
    cursor=printBuffer(cursor,bufferB);
    cursor=64;
    cursor=printBuffer(cursor,bufferC);

    t=millis();
    while(millis()-t&lt;1000){
      if( checkShake() ){
        reset();
        break;
      }
    }
    if(home==true)  break;

    while(tiltLeft()==false){
      delay(5);
    }

    fadeOut();
    clearLCD();
    //LINE01/////////////////////////////////////
    //article noun verb preposition article noun
    fadeIn();

    cursor=0;
    cursor=printBuffer(cursor,bufferD);
    cursor=printBuffer(cursor,bufferE);
    cursor=printBuffer(cursor,bufferF);
    cursor=64+scrollCount;
    cursor=printBuffer(cursor,bufferG);
    cursor=printBuffer(cursor,bufferH);
    cursor=printBuffer(cursor,bufferI);
    scrollCount=0;
    t=millis();
    while(millis()-t&lt;1000){
      if( checkShake() ){
        reset();
        break;
      }
    }
    if(home==true)  break;

    if(tiltLeft()==false){
      delay(10);
    }

    fadeOut();
    clearLCD();

    //LINE02//////////////////////////////////
    //adjective adjective noun
    fadeIn();

    cursor=0;
    cursor=printBuffer(cursor,bufferJ);
    cursor=printBuffer(cursor,bufferK);
    cursor=64;
    cursor=printBuffer(cursor,bufferL);
    if(tiltLeft()==false){
      delay(5);
    }

    t=millis();
    while(millis()-t&lt;1000){
      if( checkShake() ){
        reset();
        break;
      }
    }
    if(home==true)  break;

    fadeOut();
    clearLCD();

    t=millis();
    while(millis()-t&lt;3000){
      if( checkShake() ){
        reset();
        break;
      }
    }
    if(home==true)  break;

    if( checkShake() ){
      reset();
      break;
    } 

  }
}
///////////////////////////////////////////

boolean tiltLeft(){
  boolean tilt;
  // if(millis()-tiltTimer&gt;50){
  readTilt();
  if(x&lt;-10){
    tilt=true;
  }
  else{
    tilt=false;
  }
  // tiltTimer=millis();
  //}
  return tilt;
}

boolean tiltRight(){
  boolean tilt;
  //if(millis()-tiltTimer&gt;50){
  readTilt();
  if(x&gt;10){
    tilt=true;
  }
  else{
    tilt=false;
  }
  //tiltTimer=millis();
  // }
  return tilt;
}

void switchArticle(char* article, char* object){
  if(checkVowel(object[0])){
    if (article[0]=='a' &amp;&amp; article[1]==' '){
      article[1]=='n';
      article[2]==' '; //space after text
      article[3]==NULL; //null for end of characters
    }
  }
  else{
    if (article[0]=='a' &amp;&amp; article[1]=='n'){
      article[1]=' ';
      article[2]=NULL;
    }
  }
}

boolean checkVowel(char buffer){
  boolean check;
  if(buffer=='a' || buffer=='e'  || buffer=='i' || buffer=='o' || buffer=='u'){
    check=true;
  }
  else check=false;
  return check;
}

boolean checkShake(){
  boolean check;
  int thres=150;
  if(millis()-resTimer&gt;5000){
    readTilt();
    if(y&gt;thres || y&lt;-thres || x&gt;thres || x&lt;-thres){
      // reset();
      check=true;
      resTimer=millis();
    }
    else{
      check=false;
    }
  }
  return check;
}

void splash(){
  fadeIn();
  char ags[]={
    "AGS : HaikuShake             V01"                                                                                                                                                                                                                           };
  Serial.print(ags);
  delay(1000);
  fadeOut();
  clearLCD();
  cursorPos(0);
  delay(500);
}

void readTilt(){
  x=analogRead(0)-x0; //reads and represents acceleration X
  y=analogRead(1)-y0; //reads and represents acceleration Y
}

//zero all tilt sensors
void setZero(){
  x0=analogRead(0);
  y0=analogRead(1);
  zero=true;
}

void fadeIn(){
  long fade=0;
  while(fade&lt;=28){
    Serial.print(124,BYTE);//command header
    int brightness=129+fade;
    Serial.print(brightness,BYTE);//128-157 brightness
    delay(10);
    fade++;
  }
}

void fadeOut(){
  long fade=0;
  while(fade&lt;=30){
    Serial.print(124,BYTE);//command header
    int brightness=159-fade;
    Serial.print(brightness,BYTE);//128-157 brightness
    delay(10);
    fade++;
  }
  delay(10);
}

void selectLineOne(){  //puts the cursor at line 0 char 0.
  Serial.print(0xFE, BYTE);   //command flag
  Serial.print(128, BYTE);    //position
}
void selectLineTwo(){  //puts the cursor at line 0 char 0.
  Serial.print(0xFE, BYTE);   //command flag
  Serial.print(192, BYTE);    //position
}
void clearLCD(){
  Serial.print(0xFE, BYTE);   //command flag
  Serial.print(0x01, BYTE);   //clear command.
}
void backlightOn(){  //turns on the backlight
  Serial.print(0x7C, BYTE);   //command flag for backlight stuff
  Serial.print(157, BYTE);    //light level.
}
void backlightOff(){  //turns off the backlight
  Serial.print(0x7C, BYTE);   //command flag for backlight stuff
  Serial.print(128, BYTE);     //light level for off.
}
void serCommand(){   //a general function to call the command flag for issuing all other commands
  Serial.print(0xFE, BYTE);
}
void cursorR(){
  Serial.print(0xFE, BYTE);
  Serial.print(0x14, BYTE);
}
void cursorL(){
  Serial.print(0xFE, BYTE);
  Serial.print(0x10, BYTE);
}
void scrollR(){
  Serial.print(0xFE, BYTE);
  Serial.print(0x1C, BYTE);
}
void scrollL(){
  Serial.print(0xFE, BYTE);
  Serial.print(0x18, BYTE);
}
void cursorPos(int pos){
  Serial.print(0xFE, BYTE);
  Serial.print(128+pos, BYTE);
}
</j*10.0){></avr>