Akafugu / flw

Dependencies:   _24LCXXX

Dependents:   vfd_modular_clock_mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers flw.cpp Source File

flw.cpp

00001 /*
00002  * Four Letter Word Generator
00003  * (C) 2015 Akafugu Corporation
00004  *
00005  * This program is free software; you can redistribute it and/or modify it under the
00006  * terms of the GNU General Public License as published by the Free Software
00007  * Foundation; either version 2 of the License, or (at your option) any later
00008  * version.
00009  *
00010  * This program is distributed in the hope that it will be useful, but WITHOUT ANY
00011  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
00012  * PARTICULAR PURPOSE.  See the GNU General Public License for more details.
00013  *
00014  */
00015 
00016 /*
00017  * To use this Four Letter Word generator you will need the following:
00018  *
00019  * - A 512kbit/64kb I2C EEPROM
00020  * - A database file, generated from this Processing application:
00021  *   https://github.com/perjg/fourletterword
00022  * - A method for uploading the data file to the EEPROM
00023  *   (Either an Arduino Mega, or a normal Arduino with a micro SD card)
00024  */
00025 
00026 #include <string.h>
00027 #include "flw.h"
00028 #include "flw_blacklist.h"
00029 
00030 
00031 #define EEPROM_ADDR 0b1010000
00032 
00033 void FourLetterWordBase::rot13(char* w)
00034 {
00035     while (*w != '\0') {
00036         if (*w >= 'A' && *w <= 'M') {
00037             *w += 13;
00038         }
00039         else if (*w >= 'N' && *w <= 'Z') {
00040             *w -= 13;
00041         }
00042 
00043       w++;
00044     }
00045 }
00046 
00047 bool FourLetterWordBase::binary_search(const char *key, int imin, int imax)
00048 {
00049   int pos;
00050   int cond = 0;
00051   char buf[5];
00052 
00053   while (imin <= imax) {
00054     pos = (imin+imax) / 2;
00055     
00056     strcpy(buf, flw_blacklist[pos]);
00057     rot13(buf);
00058     cond = strcmp(key, buf);
00059     
00060     if (cond == 0)   return true;
00061     else if (cond>0) imin = pos+1;
00062     else             imax = pos-1;
00063   }
00064   
00065   return false;
00066 }
00067 
00068 void FourLetterWordBase::begin(uint32_t seed, bool censored)
00069 {
00070   m_lfsr = seed + 1;
00071   m_censored = censored;
00072 }
00073 
00074 uint32_t FourLetterWordBase::randomize()
00075 {
00076   // http://en.wikipedia.org/wiki/Linear_feedback_shift_register
00077   // Galois LFSR: taps: 32 31 29 1; characteristic polynomial: x^32 + x^31 + x^29 + x + 1 */
00078   m_lfsr = (m_lfsr >> 1) ^ (-(m_lfsr & 1u) & 0xD0000001u);
00079   return m_lfsr;  
00080 }
00081 
00082 bool FourLetterWordBase::hasEeprom()
00083 {
00084    uint8_t b1 = read_byte(0); 
00085    uint8_t b2 = read_byte(1); 
00086    
00087    if (b1 == 65 && b2 == 66)
00088      return true;
00089    return false;
00090 }
00091 
00092 char* FourLetterWordBase::get_word_censored()
00093 {
00094   char* w = get_word_uncensored();
00095   
00096   // assume a maximum of 5 censored words chosen in a row
00097   for (uint8_t i = 0; i < 5; i++) {
00098     if (binary_search(w, 0, BLACKLIST_SIZE)) { // censored
00099       w = get_word_uncensored();
00100     }
00101     else
00102       return w;
00103   }
00104   
00105   return w;
00106 }
00107 
00108 char* FourLetterWordBase::get_word_uncensored()
00109 {
00110   unsigned char low = 0xFF, high = 0xFF;
00111   unsigned char count = 0;
00112   int next = 0;
00113 
00114   read_buffer(m_offset, (uint8_t*)m_current_word, 5);
00115   count = m_current_word[4];
00116   m_current_word[4] = '\0';
00117 
00118   next = randomize() % count;
00119   m_offset += 5 + next * 2;
00120 
00121   high = read_byte(m_offset++);
00122   low  = read_byte(m_offset++);
00123 
00124   m_offset = (high << 8) | low;
00125 
00126   return m_current_word;
00127 }
00128 
00129 char* FourLetterWordBase::getWord(bool adjustCase)
00130 {
00131   char* ret;
00132   
00133   if (m_censored) ret = get_word_censored();
00134   ret = get_word_uncensored();
00135   
00136   if (adjustCase) {
00137     // lowercase letters
00138     ret[1] += 32;
00139     ret[2] += 32;
00140     ret[3] += 32;
00141   }
00142   
00143   return ret;
00144 }
00145 
00146 /////////////////////////////////////////////////////
00147 // EEPROM
00148 
00149 uint8_t FourLetterWord::read_byte(unsigned int addr) {
00150   uint8_t rdata = 0xFF;
00151   
00152   _24lc.nbyte_read(addr, &rdata, 1);
00153   return rdata;
00154 }
00155 
00156 void FourLetterWord::read_buffer(unsigned int addr, uint8_t *buffer, int length) {
00157   _24lc.nbyte_read(addr, buffer, length);
00158 }
00159 
00160 /////////////////////////////////////////////////////
00161 // Data stored in local array
00162 
00163 uint8_t FourLetterWordLocal::read_byte(unsigned int addr) {
00164   return data[addr];  
00165 }
00166 
00167 void FourLetterWordLocal::read_buffer(unsigned int addr, uint8_t *buffer, int length) {
00168   unsigned char* ptr = (unsigned char*)data;
00169   ptr += addr;
00170   memcpy(buffer, ptr, length); 
00171 }
00172 
00173 
00174