Four Letter Word generator based on an associative word dictionary.

Dependencies:   _24LCXXX

Dependents:   vfd_modular_clock_mbed

Four Letter Word generator based on an associative word dictionary.

Needs an EEPROM to function (can be programmed onto a 24LC512 I2C EEPROM, or available as a pre-programmed add-on board)

Comes with a censored mode that removes expletives as well as a fully uncensored mode.

For details see:

Committer:
Backstrom
Date:
Fri Jan 13 06:58:52 2017 +0000
Revision:
9:93f52963c4ff
Parent:
6:f3455eff2ae4
New version of _24LCXXX

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Backstrom 0:4d3dec05a4b7 1 /*
Backstrom 0:4d3dec05a4b7 2 * Four Letter Word Generator
Backstrom 0:4d3dec05a4b7 3 * (C) 2015 Akafugu Corporation
Backstrom 0:4d3dec05a4b7 4 *
Backstrom 0:4d3dec05a4b7 5 * This program is free software; you can redistribute it and/or modify it under the
Backstrom 0:4d3dec05a4b7 6 * terms of the GNU General Public License as published by the Free Software
Backstrom 0:4d3dec05a4b7 7 * Foundation; either version 2 of the License, or (at your option) any later
Backstrom 0:4d3dec05a4b7 8 * version.
Backstrom 0:4d3dec05a4b7 9 *
Backstrom 0:4d3dec05a4b7 10 * This program is distributed in the hope that it will be useful, but WITHOUT ANY
Backstrom 0:4d3dec05a4b7 11 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
Backstrom 0:4d3dec05a4b7 12 * PARTICULAR PURPOSE. See the GNU General Public License for more details.
Backstrom 0:4d3dec05a4b7 13 *
Backstrom 0:4d3dec05a4b7 14 */
Backstrom 0:4d3dec05a4b7 15
Backstrom 0:4d3dec05a4b7 16 /*
Backstrom 0:4d3dec05a4b7 17 * To use this Four Letter Word generator you will need the following:
Backstrom 0:4d3dec05a4b7 18 *
Backstrom 0:4d3dec05a4b7 19 * - A 512kbit/64kb I2C EEPROM
Backstrom 0:4d3dec05a4b7 20 * - A database file, generated from this Processing application:
Backstrom 0:4d3dec05a4b7 21 * https://github.com/perjg/fourletterword
Backstrom 0:4d3dec05a4b7 22 * - A method for uploading the data file to the EEPROM
Backstrom 0:4d3dec05a4b7 23 * (Either an Arduino Mega, or a normal Arduino with a micro SD card)
Backstrom 0:4d3dec05a4b7 24 */
Backstrom 0:4d3dec05a4b7 25
Backstrom 0:4d3dec05a4b7 26 #include <string.h>
Backstrom 0:4d3dec05a4b7 27 #include "flw.h"
Backstrom 0:4d3dec05a4b7 28 #include "flw_blacklist.h"
Backstrom 0:4d3dec05a4b7 29
Backstrom 0:4d3dec05a4b7 30
Backstrom 0:4d3dec05a4b7 31 #define EEPROM_ADDR 0b1010000
Backstrom 0:4d3dec05a4b7 32
perjg 6:f3455eff2ae4 33 void FourLetterWordBase::rot13(char* w)
Backstrom 0:4d3dec05a4b7 34 {
Backstrom 0:4d3dec05a4b7 35 while (*w != '\0') {
Backstrom 0:4d3dec05a4b7 36 if (*w >= 'A' && *w <= 'M') {
Backstrom 0:4d3dec05a4b7 37 *w += 13;
Backstrom 0:4d3dec05a4b7 38 }
Backstrom 0:4d3dec05a4b7 39 else if (*w >= 'N' && *w <= 'Z') {
Backstrom 0:4d3dec05a4b7 40 *w -= 13;
Backstrom 0:4d3dec05a4b7 41 }
Backstrom 0:4d3dec05a4b7 42
Backstrom 0:4d3dec05a4b7 43 w++;
Backstrom 0:4d3dec05a4b7 44 }
Backstrom 0:4d3dec05a4b7 45 }
Backstrom 0:4d3dec05a4b7 46
perjg 6:f3455eff2ae4 47 bool FourLetterWordBase::binary_search(const char *key, int imin, int imax)
Backstrom 0:4d3dec05a4b7 48 {
Backstrom 0:4d3dec05a4b7 49 int pos;
Backstrom 0:4d3dec05a4b7 50 int cond = 0;
Backstrom 0:4d3dec05a4b7 51 char buf[5];
Backstrom 0:4d3dec05a4b7 52
Backstrom 0:4d3dec05a4b7 53 while (imin <= imax) {
Backstrom 0:4d3dec05a4b7 54 pos = (imin+imax) / 2;
Backstrom 0:4d3dec05a4b7 55
Backstrom 0:4d3dec05a4b7 56 strcpy(buf, flw_blacklist[pos]);
Backstrom 0:4d3dec05a4b7 57 rot13(buf);
Backstrom 0:4d3dec05a4b7 58 cond = strcmp(key, buf);
Backstrom 0:4d3dec05a4b7 59
Backstrom 0:4d3dec05a4b7 60 if (cond == 0) return true;
Backstrom 0:4d3dec05a4b7 61 else if (cond>0) imin = pos+1;
Backstrom 0:4d3dec05a4b7 62 else imax = pos-1;
Backstrom 0:4d3dec05a4b7 63 }
Backstrom 0:4d3dec05a4b7 64
Backstrom 0:4d3dec05a4b7 65 return false;
Backstrom 0:4d3dec05a4b7 66 }
Backstrom 0:4d3dec05a4b7 67
perjg 6:f3455eff2ae4 68 void FourLetterWordBase::begin(uint32_t seed, bool censored)
Backstrom 0:4d3dec05a4b7 69 {
Backstrom 4:706c5fa05343 70 m_lfsr = seed + 1;
Backstrom 0:4d3dec05a4b7 71 m_censored = censored;
Backstrom 0:4d3dec05a4b7 72 }
Backstrom 0:4d3dec05a4b7 73
perjg 6:f3455eff2ae4 74 uint32_t FourLetterWordBase::randomize()
Backstrom 0:4d3dec05a4b7 75 {
Backstrom 0:4d3dec05a4b7 76 // http://en.wikipedia.org/wiki/Linear_feedback_shift_register
Backstrom 0:4d3dec05a4b7 77 // Galois LFSR: taps: 32 31 29 1; characteristic polynomial: x^32 + x^31 + x^29 + x + 1 */
Backstrom 0:4d3dec05a4b7 78 m_lfsr = (m_lfsr >> 1) ^ (-(m_lfsr & 1u) & 0xD0000001u);
Backstrom 0:4d3dec05a4b7 79 return m_lfsr;
Backstrom 0:4d3dec05a4b7 80 }
Backstrom 0:4d3dec05a4b7 81
perjg 6:f3455eff2ae4 82 bool FourLetterWordBase::hasEeprom()
Backstrom 0:4d3dec05a4b7 83 {
Backstrom 0:4d3dec05a4b7 84 uint8_t b1 = read_byte(0);
Backstrom 0:4d3dec05a4b7 85 uint8_t b2 = read_byte(1);
Backstrom 0:4d3dec05a4b7 86
Backstrom 0:4d3dec05a4b7 87 if (b1 == 65 && b2 == 66)
Backstrom 0:4d3dec05a4b7 88 return true;
Backstrom 0:4d3dec05a4b7 89 return false;
Backstrom 0:4d3dec05a4b7 90 }
Backstrom 0:4d3dec05a4b7 91
perjg 6:f3455eff2ae4 92 char* FourLetterWordBase::get_word_censored()
Backstrom 0:4d3dec05a4b7 93 {
Backstrom 0:4d3dec05a4b7 94 char* w = get_word_uncensored();
Backstrom 0:4d3dec05a4b7 95
Backstrom 0:4d3dec05a4b7 96 // assume a maximum of 5 censored words chosen in a row
Backstrom 0:4d3dec05a4b7 97 for (uint8_t i = 0; i < 5; i++) {
Backstrom 0:4d3dec05a4b7 98 if (binary_search(w, 0, BLACKLIST_SIZE)) { // censored
Backstrom 0:4d3dec05a4b7 99 w = get_word_uncensored();
Backstrom 0:4d3dec05a4b7 100 }
Backstrom 0:4d3dec05a4b7 101 else
Backstrom 0:4d3dec05a4b7 102 return w;
Backstrom 0:4d3dec05a4b7 103 }
Backstrom 0:4d3dec05a4b7 104
Backstrom 0:4d3dec05a4b7 105 return w;
Backstrom 0:4d3dec05a4b7 106 }
Backstrom 0:4d3dec05a4b7 107
perjg 6:f3455eff2ae4 108 char* FourLetterWordBase::get_word_uncensored()
Backstrom 0:4d3dec05a4b7 109 {
Backstrom 0:4d3dec05a4b7 110 unsigned char low = 0xFF, high = 0xFF;
Backstrom 0:4d3dec05a4b7 111 unsigned char count = 0;
Backstrom 0:4d3dec05a4b7 112 int next = 0;
Backstrom 0:4d3dec05a4b7 113
Backstrom 0:4d3dec05a4b7 114 read_buffer(m_offset, (uint8_t*)m_current_word, 5);
Backstrom 0:4d3dec05a4b7 115 count = m_current_word[4];
Backstrom 0:4d3dec05a4b7 116 m_current_word[4] = '\0';
Backstrom 0:4d3dec05a4b7 117
Backstrom 0:4d3dec05a4b7 118 next = randomize() % count;
Backstrom 0:4d3dec05a4b7 119 m_offset += 5 + next * 2;
Backstrom 0:4d3dec05a4b7 120
Backstrom 0:4d3dec05a4b7 121 high = read_byte(m_offset++);
Backstrom 0:4d3dec05a4b7 122 low = read_byte(m_offset++);
Backstrom 0:4d3dec05a4b7 123
Backstrom 0:4d3dec05a4b7 124 m_offset = (high << 8) | low;
Backstrom 0:4d3dec05a4b7 125
Backstrom 0:4d3dec05a4b7 126 return m_current_word;
Backstrom 0:4d3dec05a4b7 127 }
Backstrom 0:4d3dec05a4b7 128
perjg 6:f3455eff2ae4 129 char* FourLetterWordBase::getWord(bool adjustCase)
Backstrom 0:4d3dec05a4b7 130 {
perjg 2:ff0163bc298d 131 char* ret;
perjg 2:ff0163bc298d 132
perjg 2:ff0163bc298d 133 if (m_censored) ret = get_word_censored();
perjg 2:ff0163bc298d 134 ret = get_word_uncensored();
perjg 2:ff0163bc298d 135
perjg 2:ff0163bc298d 136 if (adjustCase) {
perjg 2:ff0163bc298d 137 // lowercase letters
perjg 2:ff0163bc298d 138 ret[1] += 32;
perjg 2:ff0163bc298d 139 ret[2] += 32;
perjg 2:ff0163bc298d 140 ret[3] += 32;
perjg 2:ff0163bc298d 141 }
perjg 2:ff0163bc298d 142
perjg 2:ff0163bc298d 143 return ret;
Backstrom 0:4d3dec05a4b7 144 }
perjg 6:f3455eff2ae4 145
perjg 6:f3455eff2ae4 146 /////////////////////////////////////////////////////
perjg 6:f3455eff2ae4 147 // EEPROM
perjg 6:f3455eff2ae4 148
perjg 6:f3455eff2ae4 149 uint8_t FourLetterWord::read_byte(unsigned int addr) {
perjg 6:f3455eff2ae4 150 uint8_t rdata = 0xFF;
perjg 6:f3455eff2ae4 151
perjg 6:f3455eff2ae4 152 _24lc.nbyte_read(addr, &rdata, 1);
perjg 6:f3455eff2ae4 153 return rdata;
perjg 6:f3455eff2ae4 154 }
perjg 6:f3455eff2ae4 155
perjg 6:f3455eff2ae4 156 void FourLetterWord::read_buffer(unsigned int addr, uint8_t *buffer, int length) {
perjg 6:f3455eff2ae4 157 _24lc.nbyte_read(addr, buffer, length);
perjg 6:f3455eff2ae4 158 }
perjg 6:f3455eff2ae4 159
perjg 6:f3455eff2ae4 160 /////////////////////////////////////////////////////
perjg 6:f3455eff2ae4 161 // Data stored in local array
perjg 6:f3455eff2ae4 162
perjg 6:f3455eff2ae4 163 uint8_t FourLetterWordLocal::read_byte(unsigned int addr) {
perjg 6:f3455eff2ae4 164 return data[addr];
perjg 6:f3455eff2ae4 165 }
perjg 6:f3455eff2ae4 166
perjg 6:f3455eff2ae4 167 void FourLetterWordLocal::read_buffer(unsigned int addr, uint8_t *buffer, int length) {
perjg 6:f3455eff2ae4 168 unsigned char* ptr = (unsigned char*)data;
perjg 6:f3455eff2ae4 169 ptr += addr;
perjg 6:f3455eff2ae4 170 memcpy(buffer, ptr, length);
perjg 6:f3455eff2ae4 171 }
perjg 6:f3455eff2ae4 172
perjg 6:f3455eff2ae4 173
perjg 6:f3455eff2ae4 174