This is a part of the Kinetiszer project.

Dependencies:   inc

Dependents:   kinetisizer

Revision:
0:cb80470434eb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/user_interface.c	Tue Oct 28 12:19:42 2014 +0000
@@ -0,0 +1,412 @@
+/*
+ * @brief User interface
+ *
+ * @note
+ * Copyright (C) Elektor, 2014
+ * All rights reserved.
+ *
+ * @par
+ * This software is supplied "AS IS" without any warranties of any kind,
+ * and Elektor and its licensor disclaim any and all warranties, express
+ * or implied, including all implied warranties of merchantability,
+ * fitness for a particular purpose and non-infringement of intellectual
+ * property rights.  Elektor assumes no responsibility or liability for
+ * the use of the software, conveys no license or rights under any patent,
+ * copyright, mask work right, or any other intellectual property rights in
+ * or to any products. Elektor reserves the right to make changes in the
+ * software without notification. Elektor also makes no representation or
+ * warranty that such application will be suitable for the specified use
+ * without further testing or modification.
+ *
+ * @par
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, under Elektor's and its licensor's
+ * relevant copyrights in the software, without fee.  This copyright,
+ * permission, and disclaimer notice must appear in all copies of this code.
+ */
+
+#include "lcd.h"
+#include "atmegatron.h"
+#include "board.h"
+
+
+#define FUNCTION_VALUE_OFFSET  (13)
+
+
+uint8_t display_page = (uint8_t)-1;
+boolean display_page_changed = false;
+
+
+const char *functions_str[FUNC_MAX][2] =
+{
+	{ "Waveform bank ", "" },
+	{ "Filter ", "(norming)" },
+	{ "Env1 attack", "Inverted" },
+	{ "Env1 dec/rel", "Inverted" },
+	{ "Env1 sustain", "Inverted" },
+	{ "Env2 attack", "SysEx write" },
+	{ "Env2 decay", "SysEx read" },
+	{ "Env2 sustain", "User wave" },
+	{ "Env2 release", "SysEx bank" },
+	{ "LFO shape ", "(inv)" },
+	{ "LFO rate ", "" },
+	{ "Arpeggio ", "(pp)" },
+	{ "Arpeggio rate", "" },
+	{ "Portamento", "Proportional" },
+	{ "Crusher ", "pre-filter" },
+	{ "Patch number", "Empty" },
+};
+
+
+const char *wave_str[FUNC_MAX][2] =
+{
+	{ "Pure square", "Metallic 1" },
+	{ "Octave square", "Metallic 2" },
+	{ "Square fifths", "Metallic 3" },
+	{ "RP2A07 square ", "Metallic 4" },
+	{ "Pure saw", "Vocal 1" },
+	{ "Buzz saw", "Vocal 2" },
+	{ "Saw fifths", "Vocal 3" },
+	{ "Octave saw", "Brass" },
+	{ "Subsine + square", "Reed organ" },
+	{ "Pure sine", "Electric piano" },
+	{ "PPG sine", "Reed" },
+	{ "Warped sine ", "Resonant saw" },
+	{ "CZ101 pulse", "Bell" },
+	{ "Bassoon", "Chord" },
+	{ "Bass", "Overtones" },
+	{ "Noise", "Saw thirds" },
+};
+
+
+const char *filter_str[FUNC_MAX] =
+{
+	"Bypassed",
+	"Low pass",
+	"High pass",
+	"Band pass",
+	"Notch",
+	"Param EQ 10 dB",
+	"Param EQ 30 dB",
+	"Param EQ 100 dB",
+	"LO shelf 10 dB",
+	"LO shelf 30 dB",
+	"HI shelf 10 dB",
+	"HI shelf 30 dB",
+	"Butter LP (no Q)",
+	"Butter HP (no Q)",
+	"Bessel LP (no Q)",
+	"Bessel HP (no Q)",
+};
+
+
+const char *lfo_str[FUNC_MAX] =
+{
+	"Sine",
+	"Triangle",
+	"Ramp down (lin)",
+	"Ramp up (exp)",
+	"Sine + 3rd",
+	"Pulse  5%",
+	"Pulse 25%",
+	"Pulse 50%",
+	"Pulse 75%",
+	"Pulse 95%",
+	"Ramp up & hold",
+	"Hold & ramp down",
+	"Duh dugga",
+	"Dugga duh",
+	"Noise-like",
+	"DC",
+};
+
+
+const char *arp_str[FUNC_MAX] =
+{
+	"Off",
+	"Up",
+	"Down",
+	"Octave",
+	"Fifths",
+	"Skip one up",
+	"Skip one down",
+	"I feel love",
+	"Horton",
+	"Etheridge",
+	"Meads",
+	"Palmer",
+	"gwEm 1",
+	"gwEm 2",
+	"Triplet up",
+	"Robyn",
+};
+
+const char *rate_str[FUNC_MAX] =
+{
+	"4",
+	"2",
+	"1",
+	"3/4",
+	"2/3",
+	"1/2",
+	"3/8",
+	"1/3",
+	"1/4",
+	"3/16",
+	"1/8",
+	"3/32",
+	"1/16",
+	"3/64",
+	"1/32",
+	"1/64",
+};
+
+
+const char *crusher_str[FUNC_MAX] =
+{
+	"Off",
+	"3 bit",
+	"2 bit",
+	"1 bit",
+	"4 bit, SR/2",
+	"3 bit, SR/2",
+	"2 bit, SR/2",
+	"1 bit, SR/2",
+	"4 bit, SR/4",
+	"3 bit, SR/4",
+	"2 bit, SR/4",
+	"1 bit, SR/4",
+	"4 bit, SR/8",
+	"3 bit, SR/8",
+	"2 bit, SR/8",
+	"1 bit, SR/8",
+};
+
+
+/*const char *controls_str[CTRL_MAX][2] =
+{
+	// Digital controls (potentiometers)
+	{ "Filt cutoff", "Filt cutoff" },
+	{ "Filter Q", "Filter Q" },
+	{ "Filter env", "Pitch env" },
+	{ "Filter LFO", "Pitch LFO" },
+	{ "Amp LFO", "PW LFO" },
+	{ "Distortion", "Phase LFO" },
+};*/
+
+
+void display_init(void)
+{
+	// Setup LCD.
+	lcd_init();
+	display_page_set(PAGE_SPLASH);
+}
+
+
+void display_print_value(uint8_t line, uint8_t position, int value, boolean ignore_sign)
+{
+	int scale = 100;
+
+	lcd_clear_to_eol(line,position);
+	if (ignore_sign==false)
+	{
+		if (value<0)
+		{
+			lcd_putc('-');
+			value = -value;
+		}
+		else lcd_putc(' ');
+	}
+
+	if (value<100)
+	{
+		lcd_putc(' ');
+		scale = 10;
+	}
+	if (value<10)
+	{
+		lcd_putc(' ');
+		scale = 1;
+	}
+
+	do
+	{
+		int temp = value/scale;
+		lcd_putc(temp+'0');
+		value -= temp*scale;
+		scale /= 10;
+	}
+	while (scale>0);
+}
+
+
+void display_page_splash(void)
+{
+	lcd_clear();
+	lcd_font(ST7032_FUNC_HEIGHT_DOUBLE);
+	lcd_puts("J2B Synthesizer");
+	SysTick_Delay(1500);
+	lcd_font(ST7032_FUNC_HEIGHT_NORMAL);
+	display_page_set(PAGE_FUNCTION);
+}
+
+
+void display_page_function(void)
+{
+	uint8_t function = Hardware_Get_Function();
+	boolean shift = Hard_Get_Shift(function);
+	uint8_t value = Hardware_Get_Value(function);
+
+	lcd_clear();
+	if (function>=FUNC_MAX)
+	{
+		lcd_puts((char*)"undefined");
+	}
+	else
+	{
+		lcd_puts((char*)functions_str[function][0]);
+		switch (function)
+		{
+			case FUNC_WAVE:
+				if (shift==GREEN) lcd_putc('2');
+				else lcd_putc('1');
+				lcd_cursor(1,0);
+				lcd_puts((char*)wave_str[value][shift]);
+				break;
+
+			case FUNC_FILT:
+				if (shift==GREEN) lcd_puts((char*)functions_str[function][1]);
+				lcd_cursor(1,0);
+				lcd_puts((char*)filter_str[value]);
+				break;
+
+			case FUNC_LFOTYPE:
+				if (shift==GREEN) lcd_puts((char*)functions_str[function][1]);
+				lcd_cursor(1,0);
+				lcd_puts((char*)lfo_str[value]);
+				break;
+
+			case FUNC_LFOSPEED:
+			case FUNC_ARPSPEED:
+				if (shift==GREEN) lcd_puts((char*)functions_str[function][1]);
+				lcd_cursor(1,0);
+				lcd_puts((char*)rate_str[value]);
+				break;
+
+			case FUNC_ARPTYPE:
+				if (shift==GREEN) lcd_puts((char*)functions_str[function][1]);
+				lcd_cursor(1,0);
+				lcd_puts((char*)arp_str[value]);
+				break;
+
+			case FUNC_BITCRUSH:
+				if (shift==GREEN) lcd_puts("(pre)");
+				else lcd_puts("(post)");
+				lcd_cursor(1,0);
+				lcd_puts((char*)crusher_str[value]);
+				break;
+
+			case FUNC_MEM:
+			{
+				uint8_t buffer[MEM_PATCHSIZE];
+				display_print_value(0,FUNCTION_VALUE_OFFSET,value+1,true);
+				if (Memory_Load_Patch(buffer,value*MEM_PATCHSIZE)==false)
+				{
+					lcd_cursor(1,0);
+					lcd_puts((char*)functions_str[function][1]);
+				}
+				break;
+			}
+
+			default:
+				display_print_value(0,FUNCTION_VALUE_OFFSET,value,true);
+				if (shift==GREEN)
+				{
+					lcd_cursor(1,0);
+					lcd_puts((char*)functions_str[function][1]);
+				}
+		}
+	}
+}
+
+
+extern uint8_t encoder_to_ctrl[8];
+
+void display_page_ctrl(void)
+{
+	uint8_t i, column, value, dec;
+	uint8_t shift = Hardware_Get_Ctrl_Shift();
+
+	lcd_clear();
+
+	for (i=0; i<6; i++)
+	{
+		column = 3*(encoder_to_ctrl[i+2]-2);
+		value = Hardware_Get_Ctrl(shift,i);
+		if ((i==CTRL_AMP || i==CTRL_FX) && shift!=0)
+		{
+			lcd_cursor(1,column-1);
+			value >>= 3;
+			dec = value/10;
+			if (dec>0)
+			{
+				value -= 10*dec;
+				lcd_putc(dec+'0');
+			}
+			else lcd_putc(' ');
+			lcd_putc(value+'0');
+		}
+		else if (i==CTRL_FX && shift==0)
+		{
+			lcd_cursor(1,column);
+			lcd_putc((value>>5)+'0');
+		}
+		else
+		{
+			lcd_bar_graph(column,value,255);
+		}
+	}
+}
+
+
+boolean display_page_set(uint8_t page)
+{
+	display_page_changed = display_page!=page? true : false;
+	display_page = page;
+	return display_page_changed;
+}
+
+
+uint8_t display_page_get(void)
+{
+	return display_page;
+}
+
+
+void display_invalidate(void)
+{
+	display_page_changed = true;
+}
+
+
+void display_draw(boolean force_redraw)
+{
+	if (display_page_changed==true || force_redraw==true)
+	{
+		display_page_changed = false;
+		switch (display_page)
+		{
+			case PAGE_SPLASH:
+				display_page_splash();
+				break;
+
+			case PAGE_FUNCTION:
+				display_page_function();
+				break;
+
+			case PAGE_CTRL:
+				display_page_ctrl();
+				break;
+		}
+	}
+}