The final project of Embedde class.

Dependencies:   C12832 LM75B ESP-call MMA7660

Committer:
pkr7098
Date:
Thu Jun 03 07:09:55 2021 +0000
Revision:
2:37756b51ccdb
Parent:
1:ed1c6618f739
The final project of Embedde class.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
pkr7098 1:ed1c6618f739 1 // Talkie library
pkr7098 1:ed1c6618f739 2 // Copyright 2011 Peter Knight
pkr7098 1:ed1c6618f739 3 // This code is released under GPLv2 license.
pkr7098 1:ed1c6618f739 4
pkr7098 1:ed1c6618f739 5 #include "Talkie.h"
pkr7098 1:ed1c6618f739 6
pkr7098 1:ed1c6618f739 7 Timeout timeout;
pkr7098 1:ed1c6618f739 8 PwmOut speaker(D6);
pkr7098 1:ed1c6618f739 9
pkr7098 1:ed1c6618f739 10 #define FS 8000 // Speech engine sample rate
pkr7098 1:ed1c6618f739 11
pkr7098 1:ed1c6618f739 12 uint8_t synthPeriod;
pkr7098 1:ed1c6618f739 13 uint16_t synthEnergy;
pkr7098 1:ed1c6618f739 14 int16_t synthK1,synthK2;
pkr7098 1:ed1c6618f739 15 int8_t synthK3,synthK4,synthK5,synthK6,synthK7,synthK8,synthK9,synthK10;
pkr7098 1:ed1c6618f739 16
pkr7098 1:ed1c6618f739 17 uint8_t tmsEnergy[0x10] = {0x00,0x02,0x03,0x04,0x05,0x07,0x0a,0x0f,0x14,0x20,0x29,0x39,0x51,0x72,0xa1,0xff};
pkr7098 1:ed1c6618f739 18 uint8_t tmsPeriod[0x40] = {0x00,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2D,0x2F,0x31,0x33,0x35,0x36,0x39,0x3B,0x3D,0x3F,0x42,0x45,0x47,0x49,0x4D,0x4F,0x51,0x55,0x57,0x5C,0x5F,0x63,0x66,0x6A,0x6E,0x73,0x77,0x7B,0x80,0x85,0x8A,0x8F,0x95,0x9A,0xA0};
pkr7098 1:ed1c6618f739 19 int16_t tmsK1[0x20] = {-32064, -31872, -31808, -31680, -31552, -31424, -31232, -30848, -30592, -30336, -30016, -29696, -29376, -28928, -28480, -27968, -26368, -24256, -21632, -18368, -14528, -10048, -5184, 0, 5184, 10048, 14528, 18368, 21632, 24256, 26368, 27968};
pkr7098 1:ed1c6618f739 20 int16_t tmsK2[0x20] = {-20992, -19328, -17536, -15552, -13440, -11200, -8768, -6272, -3712, -1088, 1536, 4160, 6720, 9216, 11584, 13824, 15936, 17856, 19648, 21248, 22656, 24000, 25152, 26176, 27072, 27840, 28544, 29120, 29632, 30080, 30464, 32384};
pkr7098 1:ed1c6618f739 21 int8_t tmsK3[0x10] = {-110, -97, -83, -70, -56, -43, -29, -16, -2, 11, 25, 38, 52, 65, 79, 92};
pkr7098 1:ed1c6618f739 22 int8_t tmsK4[0x10] = {-82, -68, -54, -40, -26, -12, 1, 15};
pkr7098 1:ed1c6618f739 23 int8_t tmsK5[0x10] = {-82, -70, -59, -47, -35, -24, -12, -1, 11, 23, 34, 46, 57, 69, 81, 92};
pkr7098 1:ed1c6618f739 24 int8_t tmsK6[0x10] = {-64, -53, -42, -31, -20, -9, 3, 14, 25, 36, 47, 58, 69, 80, 91, 102};
pkr7098 1:ed1c6618f739 25 int8_t tmsK7[0x10] = {-77, -65, -53, -41, -29, -17, -5, 7, 19, 31, 43, 55, 67, 79, 90, 102};
pkr7098 1:ed1c6618f739 26 int8_t tmsK8[0x08] = {-64, -40, -16, 7, 31, 55, 79, 102};
pkr7098 1:ed1c6618f739 27 int8_t tmsK9[0x08] = {-64, -44, -24, -4, 16, 37, 57, 77};
pkr7098 1:ed1c6618f739 28 int8_t tmsK10[0x08] = {-51, -33, -15, 4, 22, 32, 59, 77};
pkr7098 1:ed1c6618f739 29
pkr7098 1:ed1c6618f739 30 void TIMEOUT(void);
pkr7098 1:ed1c6618f739 31
pkr7098 1:ed1c6618f739 32 void Talkie::setPtr(uint8_t* addr)
pkr7098 1:ed1c6618f739 33 {
pkr7098 1:ed1c6618f739 34 ptrAddr = addr;
pkr7098 1:ed1c6618f739 35 ptrBit = 0;
pkr7098 1:ed1c6618f739 36 }
pkr7098 1:ed1c6618f739 37
pkr7098 1:ed1c6618f739 38 // The ROMs used with the TI speech were serial, not byte wide.
pkr7098 1:ed1c6618f739 39 // Here's a handy routine to flip ROM data which is usually reversed.
pkr7098 1:ed1c6618f739 40 uint8_t Talkie::rev(uint8_t a)
pkr7098 1:ed1c6618f739 41 {
pkr7098 1:ed1c6618f739 42 // 76543210
pkr7098 1:ed1c6618f739 43 a = (a>>4) | (a<<4); // Swap in groups of 4
pkr7098 1:ed1c6618f739 44 // 32107654
pkr7098 1:ed1c6618f739 45 a = ((a & 0xcc)>>2) | ((a & 0x33)<<2); // Swap in groups of 2
pkr7098 1:ed1c6618f739 46 // 10325476
pkr7098 1:ed1c6618f739 47 a = ((a & 0xaa)>>1) | ((a & 0x55)<<1); // Swap bit pairs
pkr7098 1:ed1c6618f739 48 // 01234567
pkr7098 1:ed1c6618f739 49 return a;
pkr7098 1:ed1c6618f739 50 }
pkr7098 1:ed1c6618f739 51 uint8_t Talkie::getBits(uint8_t bits)
pkr7098 1:ed1c6618f739 52 {
pkr7098 1:ed1c6618f739 53 uint8_t value;
pkr7098 1:ed1c6618f739 54 uint16_t data;
pkr7098 1:ed1c6618f739 55 data = rev((*ptrAddr))<<8;
pkr7098 1:ed1c6618f739 56 if (ptrBit+bits > 8) {
pkr7098 1:ed1c6618f739 57 data |= rev((*(ptrAddr+1)));
pkr7098 1:ed1c6618f739 58 }
pkr7098 1:ed1c6618f739 59 data <<= ptrBit;
pkr7098 1:ed1c6618f739 60 value = data >> (16-bits);
pkr7098 1:ed1c6618f739 61 ptrBit += bits;
pkr7098 1:ed1c6618f739 62 if (ptrBit >= 8) {
pkr7098 1:ed1c6618f739 63 ptrBit -= 8;
pkr7098 1:ed1c6618f739 64 ptrAddr++;
pkr7098 1:ed1c6618f739 65 }
pkr7098 1:ed1c6618f739 66 return value;
pkr7098 1:ed1c6618f739 67 }
pkr7098 1:ed1c6618f739 68 void Talkie::say(uint8_t* addr)
pkr7098 1:ed1c6618f739 69 {
pkr7098 1:ed1c6618f739 70 uint8_t energy;
pkr7098 1:ed1c6618f739 71
pkr7098 1:ed1c6618f739 72 if (!setup) {
pkr7098 1:ed1c6618f739 73 // Auto-setup.
pkr7098 1:ed1c6618f739 74 //
pkr7098 1:ed1c6618f739 75 // Enable the speech system whenever say() is called.
pkr7098 1:ed1c6618f739 76
pkr7098 1:ed1c6618f739 77 // Timer 2 set up as a 62500Hz PWM.
pkr7098 1:ed1c6618f739 78 //
pkr7098 1:ed1c6618f739 79 // The PWM 'buzz' is well above human hearing range and is
pkr7098 1:ed1c6618f739 80 // very easy to filter out.
pkr7098 1:ed1c6618f739 81 //
pkr7098 1:ed1c6618f739 82 speaker.period_us(16);
pkr7098 1:ed1c6618f739 83
pkr7098 1:ed1c6618f739 84 // Unfortunately we can't calculate the next sample every PWM cycle
pkr7098 1:ed1c6618f739 85 // as the routine is too slow. So use Timer 1 to trigger that.
pkr7098 1:ed1c6618f739 86
pkr7098 1:ed1c6618f739 87 // Timer 1 set up as a 8000Hz sample interrupt
pkr7098 1:ed1c6618f739 88 timeout.attach_us(TIMEOUT, 125);
pkr7098 1:ed1c6618f739 89
pkr7098 1:ed1c6618f739 90 setup = 1;
pkr7098 1:ed1c6618f739 91 }
pkr7098 1:ed1c6618f739 92
pkr7098 1:ed1c6618f739 93 setPtr(addr);
pkr7098 1:ed1c6618f739 94 do {
pkr7098 1:ed1c6618f739 95 uint8_t repeat;
pkr7098 1:ed1c6618f739 96
pkr7098 1:ed1c6618f739 97 // Read speech data, processing the variable size frames.
pkr7098 1:ed1c6618f739 98
pkr7098 1:ed1c6618f739 99 energy = getBits(4);
pkr7098 1:ed1c6618f739 100 if (energy == 0) {
pkr7098 1:ed1c6618f739 101 // Energy = 0: rest frame
pkr7098 1:ed1c6618f739 102 synthEnergy = 0;
pkr7098 1:ed1c6618f739 103 } else if (energy == 0xf) {
pkr7098 1:ed1c6618f739 104 // Energy = 15: stop frame. Silence the synthesiser.
pkr7098 1:ed1c6618f739 105 synthEnergy = 0;
pkr7098 1:ed1c6618f739 106 synthK1 = 0;
pkr7098 1:ed1c6618f739 107 synthK2 = 0;
pkr7098 1:ed1c6618f739 108 synthK3 = 0;
pkr7098 1:ed1c6618f739 109 synthK4 = 0;
pkr7098 1:ed1c6618f739 110 synthK5 = 0;
pkr7098 1:ed1c6618f739 111 synthK6 = 0;
pkr7098 1:ed1c6618f739 112 synthK7 = 0;
pkr7098 1:ed1c6618f739 113 synthK8 = 0;
pkr7098 1:ed1c6618f739 114 synthK9 = 0;
pkr7098 1:ed1c6618f739 115 synthK10 = 0;
pkr7098 1:ed1c6618f739 116 } else {
pkr7098 1:ed1c6618f739 117 synthEnergy = tmsEnergy[energy];
pkr7098 1:ed1c6618f739 118 repeat = getBits(1);
pkr7098 1:ed1c6618f739 119 synthPeriod = tmsPeriod[getBits(6)];
pkr7098 1:ed1c6618f739 120 // A repeat frame uses the last coefficients
pkr7098 1:ed1c6618f739 121 if (!repeat) {
pkr7098 1:ed1c6618f739 122 // All frames use the first 4 coefficients
pkr7098 1:ed1c6618f739 123 synthK1 = tmsK1[getBits(5)];
pkr7098 1:ed1c6618f739 124 synthK2 = tmsK2[getBits(5)];
pkr7098 1:ed1c6618f739 125 synthK3 = tmsK3[getBits(4)];
pkr7098 1:ed1c6618f739 126 synthK4 = tmsK4[getBits(4)];
pkr7098 1:ed1c6618f739 127 if (synthPeriod) {
pkr7098 1:ed1c6618f739 128 // Voiced frames use 6 extra coefficients.
pkr7098 1:ed1c6618f739 129 synthK5 = tmsK5[getBits(4)];
pkr7098 1:ed1c6618f739 130 synthK6 = tmsK6[getBits(4)];
pkr7098 1:ed1c6618f739 131 synthK7 = tmsK7[getBits(4)];
pkr7098 1:ed1c6618f739 132 synthK8 = tmsK8[getBits(3)];
pkr7098 1:ed1c6618f739 133 synthK9 = tmsK9[getBits(3)];
pkr7098 1:ed1c6618f739 134 synthK10 = tmsK10[getBits(3)];
pkr7098 1:ed1c6618f739 135 }
pkr7098 1:ed1c6618f739 136 }
pkr7098 1:ed1c6618f739 137 }
pkr7098 1:ed1c6618f739 138 thread_sleep_for(25);
pkr7098 1:ed1c6618f739 139 } while (energy != 0xf);
pkr7098 1:ed1c6618f739 140 }
pkr7098 1:ed1c6618f739 141
pkr7098 1:ed1c6618f739 142 #define CHIRP_SIZE 41
pkr7098 1:ed1c6618f739 143 int8_t chirp[CHIRP_SIZE] = {0, 42, -44, 50, -78, 18, 37, 20, 2, -31, -59, 2, 95, 90, 5, 15, 38, -4, -91, -91, -42, -35, -36, -4, 37, 43, 34, 33, 15, -1, -8, -18, -19, -17, -9, -10, -6, 0, 3, 2, 1};
pkr7098 1:ed1c6618f739 144 void TIMEOUT(void)
pkr7098 1:ed1c6618f739 145 {
pkr7098 1:ed1c6618f739 146 static uint8_t nextPwm;
pkr7098 1:ed1c6618f739 147 static uint8_t periodCounter;
pkr7098 1:ed1c6618f739 148 static int16_t x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,x10;
pkr7098 1:ed1c6618f739 149 int16_t u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10;
pkr7098 1:ed1c6618f739 150
pkr7098 1:ed1c6618f739 151 speaker = float(nextPwm) * 0.392;
pkr7098 1:ed1c6618f739 152 // sei();
pkr7098 1:ed1c6618f739 153 if (synthPeriod) {
pkr7098 1:ed1c6618f739 154 // Voiced source
pkr7098 1:ed1c6618f739 155 if (periodCounter < synthPeriod) {
pkr7098 1:ed1c6618f739 156 periodCounter++;
pkr7098 1:ed1c6618f739 157 } else {
pkr7098 1:ed1c6618f739 158 periodCounter = 0;
pkr7098 1:ed1c6618f739 159 }
pkr7098 1:ed1c6618f739 160 if (periodCounter < CHIRP_SIZE) {
pkr7098 1:ed1c6618f739 161 u10 = ((chirp[periodCounter]) * (uint32_t) synthEnergy) >> 8;
pkr7098 1:ed1c6618f739 162 } else {
pkr7098 1:ed1c6618f739 163 u10 = 0;
pkr7098 1:ed1c6618f739 164 }
pkr7098 1:ed1c6618f739 165 } else {
pkr7098 1:ed1c6618f739 166 // Unvoiced source
pkr7098 1:ed1c6618f739 167 static uint16_t synthRand = 1;
pkr7098 1:ed1c6618f739 168 synthRand = (synthRand >> 1) ^ ((synthRand & 1) ? 0xB800 : 0);
pkr7098 1:ed1c6618f739 169 u10 = (synthRand & 1) ? synthEnergy : -synthEnergy;
pkr7098 1:ed1c6618f739 170 }
pkr7098 1:ed1c6618f739 171 // Lattice filter forward path
pkr7098 1:ed1c6618f739 172 u9 = u10 - (((int16_t)synthK10*x9) >> 7);
pkr7098 1:ed1c6618f739 173 u8 = u9 - (((int16_t)synthK9*x8) >> 7);
pkr7098 1:ed1c6618f739 174 u7 = u8 - (((int16_t)synthK8*x7) >> 7);
pkr7098 1:ed1c6618f739 175 u6 = u7 - (((int16_t)synthK7*x6) >> 7);
pkr7098 1:ed1c6618f739 176 u5 = u6 - (((int16_t)synthK6*x5) >> 7);
pkr7098 1:ed1c6618f739 177 u4 = u5 - (((int16_t)synthK5*x4) >> 7);
pkr7098 1:ed1c6618f739 178 u3 = u4 - (((int16_t)synthK4*x3) >> 7);
pkr7098 1:ed1c6618f739 179 u2 = u3 - (((int16_t)synthK3*x2) >> 7);
pkr7098 1:ed1c6618f739 180 u1 = u2 - (((int32_t)synthK2*x1) >> 15);
pkr7098 1:ed1c6618f739 181 u0 = u1 - (((int32_t)synthK1*x0) >> 15);
pkr7098 1:ed1c6618f739 182
pkr7098 1:ed1c6618f739 183 // Output clamp
pkr7098 1:ed1c6618f739 184 if (u0 > 511) u0 = 511;
pkr7098 1:ed1c6618f739 185 if (u0 < -512) u0 = -512;
pkr7098 1:ed1c6618f739 186
pkr7098 1:ed1c6618f739 187 // Lattice filter reverse path
pkr7098 1:ed1c6618f739 188 x9 = x8 + (((int16_t)synthK9*u8) >> 7);
pkr7098 1:ed1c6618f739 189 x8 = x7 + (((int16_t)synthK8*u7) >> 7);
pkr7098 1:ed1c6618f739 190 x7 = x6 + (((int16_t)synthK7*u6) >> 7);
pkr7098 1:ed1c6618f739 191 x6 = x5 + (((int16_t)synthK6*u5) >> 7);
pkr7098 1:ed1c6618f739 192 x5 = x4 + (((int16_t)synthK5*u4) >> 7);
pkr7098 1:ed1c6618f739 193 x4 = x3 + (((int16_t)synthK4*u3) >> 7);
pkr7098 1:ed1c6618f739 194 x3 = x2 + (((int16_t)synthK3*u2) >> 7);
pkr7098 1:ed1c6618f739 195 x2 = x1 + (((int32_t)synthK2*u1) >> 15);
pkr7098 1:ed1c6618f739 196 x1 = x0 + (((int32_t)synthK1*u0) >> 15);
pkr7098 1:ed1c6618f739 197 x0 = u0;
pkr7098 1:ed1c6618f739 198
pkr7098 1:ed1c6618f739 199 nextPwm = (u0>>2)+0x80;
pkr7098 1:ed1c6618f739 200 }