Use symmetry to store only 1/4 of a sine wave

This shrinks the sine_wave array by 190 bytes, but requires a bit more
complex code to calculate any value which takes up 42 extra bytes of flash.
So, overall we save 148 bytes of flash.

   text	   data	    bss	    dec	    hex	filename
   1530	      2	     33	   1565	    61d	fmfox-atmega48p.elf (before)
   1382	      2	     33	   1417	    589	fmfox-atmega48p.elf (after)

Additionally, this fixes slight offset in the negative half-cycle.
Previously, the mean of the sine wave was 127.5 instead of 128 as one would
expect from a sine wave.

Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
3 files changed, 35 insertions(+), 3 deletions(-)

M fmfox.h
M gen-wave.py
M main.c
M fmfox.h +1 -1
@@ 46,7 46,7 @@ 
 /*
  * Various tone sequences
  */
-extern const __flash uint8_t sine_wave[WAVE_STEPS];
+extern const __flash uint8_t sine_wave[WAVE_STEPS / 4 + 1];
 extern const __flash uint8_t tones_fixed[10];
 extern const __flash uint8_t tones_lfsr[16];
 extern const __flash uint8_t tones_morse[2];

          
M gen-wave.py +1 -1
@@ 32,7 32,7 @@ print("#if WAVE_STEPS != %u" % WAVE_STEP
 print("#error \"WAVE_STEPS doesn't match gen-wave.py\"")
 print("#endif")
 print("const __flash uint8_t sine_wave[] = {")
-for i in range(WAVE_STEPS):
+for i in range(WAVE_STEPS // 4 + 1):
     print("[%u] = %u," %
             (i, 127 * math.sin(2 * math.pi * i / WAVE_STEPS) + 128))
 print("};")

          
M main.c +33 -1
@@ 139,6 139,38 @@ static void dac_write(uint8_t val)
  * Audio
  */
 
+static inline uint8_t get_wave(uint8_t idx)
+{
+	bool reverse;
+	bool negate;
+
+	if (idx < (1 * WAVE_STEPS / 4)) {
+		reverse = false;
+		negate = false;
+		idx -= 0;
+	} else if (idx < (2 * WAVE_STEPS / 4)) {
+		reverse = true;
+		negate = false;
+		idx -= 1 * WAVE_STEPS / 4;
+	} else if (idx < (3 * WAVE_STEPS / 4)) {
+		reverse = false;
+		negate = true;
+		idx -= 2 * WAVE_STEPS / 4;
+	} else {
+		reverse = true;
+		negate = true;
+		idx -= 3 * WAVE_STEPS / 4;
+	}
+
+	if (reverse)
+		idx = (WAVE_STEPS / 4) - idx;
+
+	if (negate)
+		return 128 - sine_wave[idx] + 128;
+
+	return sine_wave[idx];
+}
+
 static inline uint8_t first_fixed_tone(void)
 {
 	return 0;

          
@@ 204,7 236,7 @@ void gen_sample(void)
 	 * sent through the DAC.  The actual latching of the previous sample
 	 * is done in the assembly isr.
 	 */
-	dac_write(sine_wave[phase]);
+	dac_write(get_wave(phase));
 
 	steps--;
 	sample_num++;