This is a part of the Kinetiszer project.

Dependencies:   inc

Dependents:   kinetisizer

user_interface.c

Committer:
Clemo
Date:
2014-10-28
Revision:
1:8ae4ab73ca6a
Parent:
0:cb80470434eb

File content as of revision 1:8ae4ab73ca6a:

/*
 * @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;
		}
	}
}