/*
 * ind.c
 *
 *  Created on: Oct 10, 2011
 *      Author: qwer1
 */

#include <string.h>
#include "ind.h"
#include "ul_timing.h"
#include "ul_lcda.h"
#include "ul_bcd.h"
#include "adc.h"
#include "config.h"
#include "process.h"
#include "ul_kbd.h"
#include "pid.h"
#include "heaters.h"
#include "kbd.h"
#include "setup.h"

U8  ind_mode;
U8  ind_update;

U16 ind_startup_tmr = (IND_STARTUP_TIME * 1000);

U8  edit_param;

#define IND_BLINK_PERIOD 6
U16 ind_blink_cnt;
#define ind_blink() (ind_blink_cnt < (U16)(IND_BLINK_PERIOD / 2))

void setup_ind( void ) {
	GPIO_InitTypeDef GPIO_InitStructure;

	// initialize GPIO
	GPIO_StructInit(&GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_8;
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);

	//test for 20x04 LCD
	GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IPU;
//	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	*BITP(&GPIOB->ODR, 5) = 0;
	delay_us(10);
	if (*BITP(&GPIOB->IDR, 3) == 0) lcd_2col_shift = 4;
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
	GPIO_Init(GPIOB, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_13;
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
	GPIO_Init(GPIOC, &GPIO_InitStructure);

	setup_lcd(0, 0);
	ind_mode = IND_MO_STARTUP;

	//indication refresh thread
	ptx_add( pt_ind, NULL, PTX_FLAG_RUN | PTX_FLAG_SYNC_100MS);
}

void put_t(S16 t, U8 *buf, U8 show_deg) {
	if (!t_is_ok(t)) *(buf+2) = '-';//memset(buf, '-', 3);
	else {
		NUM2ASC_S32(t, buf+2, 3, 0, 1, 1);
		if (show_deg) *(buf+3) = 0xDF;
	}
}

PT_THREAD( pt_ind( struct pt *pt, struct ptx *ptx ) ) {

	if (++ind_blink_cnt >= IND_BLINK_PERIOD) ind_blink_cnt = 0;

	PT_BEGIN(pt);
	while (1) {

		U8 blink = ind_blink();

		//show startup screen
		if (ind_mode == IND_MO_STARTUP) {
			memcpy((char *)&lcd_buf[0],
				"  Reflow oven   "
				"   controller   "
				"    (c) U.Z.    "
				" V              ",
				64
			);
			memcpy((char *)&lcd_buf[50], project_ver, 3);
			memcpy((char *)&lcd_buf[54], project_date, 8);
			PTX_DELAY_MS(IND_STARTUP_TIME * 1000);
			ind_mode = IND_MO_NORMAL;
		}

		//normal mode - show current program/step parameters
		else if (ind_mode == IND_MO_NORMAL) {
			memset(&lcd_buf, ' ', LCD_BUF_SIZE);

			U8 key_up = process.run && (edit_param == EDIT_PARAM_NONE)&&(kbd_code == KBD_CO_UP)&&(kbd_cnt > KBD_PR_SHORT);
			if (key_up) {

				NUM2ASC_S32(process.t_set_current[0], &lcd_buf[21], 6, 4, 1, 1);
				NUM2ASC_S32(process.t_step[0], &lcd_buf[27], 6, 4, 1, 1);
				NUM2ASC_S32(pids[0].out, &lcd_buf[31], 4, 0, 1, 1);
//				NUM2ASC_S32(t_int, &lcd_buf[31], 4, 0, 1, 1);

			} else {
				memcpy((char *)&lcd_buf[16], " t1  t2  t3  t4 ", 16);
				lcd_buf[16] = heater_enabled(0) ? '+' : '-';
				lcd_buf[20] = heater_enabled(1) ? '+' : '-';
				lcd_buf[24] = heater_enabled(2) ? '+' : '-';
				lcd_buf[28] = heater_enabled(3) ? '+' : '-';
			}

//				NUM2ASC_S32(quartz_is_enabled, &lcd_buf[19], 5, 0, 1, 1);
//				NUM2ASC_S32(config_update_cnt, &lcd_buf[19], 5, 0, 1, 1);
//				NUM2ASC_S32(config_record, &lcd_buf[22], 2, 0, 1, 1);
//				NUM2ASC_S32(CONFIG_RECORDS, &lcd_buf[25], 2, 0, 1, 1);

//				NUM2ASC_S32(t_int, &lcd_buf[19], 5, 0, 1, 1);
//				NUM2ASC_S32(adc_data[5], &lcd_buf[26], 7, 0, 1, 1);
//				NUM2ASC_S32(t_tc[0], &lcd_buf[28], 5, 0, 1, 1);
//				NUM2ASC_S32(kbd_cnt, &lcd_buf[27], 2, 0, 0, 1);
//				NUM2ASC_S32(kbd_code, &lcd_buf[31], 2, 0, 0, 1);


//			NUM2ASC_S32(config_update_cnt, &lcd_buf[31], 5, 0, 1, 1);
//			NUM2ASC_S32(config_record, &lcd_buf[20], 5, 0, 1, 1);
//			NUM2ASC_S32(CONFIG_RECORD_SIZE, &lcd_buf[19], 4, 0, 1, 1);
//			NUM2ASC_S32(CONFIG_RECORDS, &lcd_buf[22], 3, 0, 1, 1);

//			NUM2ASC_S32(process.t_set_current[0], &lcd_buf[20], 5, 3, 1, 1);
//			NUM2ASC_S32(process.t_step[0], &lcd_buf[25], 5, 3, 1, 1);
//			NUM2ASC_S32(pids[0].i_sum / pids[0].i_n, &lcd_buf[26], 5, 2, 1, 1);
//			NUM2ASC_S32(pids[0].out, &lcd_buf[31], 5, 0, 1, 1);

//			NUM2ASC_S32(p, &lcd_buf[20], 5, 0, 1, 1);
//			NUM2ASC_S32(pr, &lcd_buf[25], 5, 0, 1, 1);
//			NUM2ASC_S32(pids[0].out, &lcd_buf[31], 5, 0, 1, 1);

			//show program
			lcd_buf[1] = 'p';
			if (!((edit_param == EDIT_PARAM_PROGRAM) && blink))
				lcd_buf[2] = config.current_program + '0';

			//show step
			lcd_buf[5] = 's';
			if (!((edit_param == EDIT_PARAM_STEP) && blink))
				lcd_buf[6] = config.current_step + '0';

			//show step timer in work mode, and step time in stop mode
			if (!process.run) {
				if (!((edit_param == EDIT_PARAM_STEP_TIME) && blink))
					NUM2ASC_S32(config.programs[config.current_program][config.current_step].time, &lcd_buf[10], 3, 0, 1, 1);
			} else {
				NUM2ASC_S32(process.step_timer, &lcd_buf[10], 3, 0, 1, 1);
			}
//			lcd_buf[11] = 's';

			//show ambient temperature in STOP, or main timer in RUN
			if (!process.run) {
				NUM2ASC_S32((t_cold + 5) / 10, &lcd_buf[13], 2, 0, 1, 1);
				lcd_buf[14] = 0xDF;
			} else {
				U16 mins = process.program_time / 60;
				U8  secs = process.program_time % 60;
				if (mins <= 9) {
					NUM2ASC_S32(mins, &lcd_buf[12], 1, 0, 0, 0);
					lcd_buf[13] = '.';
					NUM2ASC_S32(secs, &lcd_buf[15], 2, 0, 1, 0);
				} else if (mins <= 99) {
					NUM2ASC_S32(mins, &lcd_buf[13], 2, 0, 1, 1);
					lcd_buf[14] = '.';
					NUM2ASC_S32(secs / 10, &lcd_buf[15], 1, 0, 0, 0);
				} else {
					NUM2ASC_S32(mins, &lcd_buf[15], 4, 0, 1, 1);
				}
			}

			//show current step temperatures
			U8 *buf = &lcd_buf[32];
			struct program_step_struct *step = &config.programs[config.current_program][config.current_step];
			for (U8 i=0; i<4; i++) {
				if (key_up && process.run) {
					NUM2ASC_S32(process.t_set_current[i] / 1000, buf+2, 3, 0, 1, 1);
					*(buf+3) = 0xDF;
				} else if (!((edit_param == EDIT_PARAM_STEP_T1 + i) && blink)) {
					U16 t = step->t_set[i];
					if (t == 0) *(buf+2) = '-';//memset(buf, '-', 3);
					else {
						NUM2ASC_S32(t, buf+2, 3, 0, 1, 1);
						*(buf+3) = 0xDF;
					}
				}
				buf += 4;
			}

			//show measured temperatures
			buf = &lcd_buf[48];
			for (U8 i=0; i<4; i++) {
				S16 t = t_tc[i];
				if (!t_is_ok(t)) put_t(t, buf, 1);
				else put_t((t + 5) / 10, buf, 1);
				buf += 4;
			}

			//show work mode
			if (!process.run) {/*if (!blink) lcd_buf[0] = 0xC9;*/}
			else {
				if (!blink) {
					if (process.pause) lcd_buf[0] = '_';
					else lcd_buf[0] = '>';
				}
			}
		}

		//configuration edit mode - show current parameter name/value
		else if ((ind_mode == IND_MO_CONFIG)||(ind_mode == IND_MO_CONFIG_ED)) {
			memset(&lcd_buf, ' ', LCD_BUF_SIZE);

			//show name
			if (!((ind_mode == IND_MO_CONFIG) && blink))
				memcpy((char *)&lcd_buf[0], params_info[param_num].name, 4);

			//show value
			if (!((ind_mode == IND_MO_CONFIG_ED) && blink))
				num2asc_S32(config.params[param_num], &lcd_buf[7], params_info[param_num].options);

			//show ambient temperature
			lcd_buf[16] = 't'; lcd_buf[17] = 'a';
			NUM2ASC_S32(t_cold, &lcd_buf[23], 4, 2, 1, 1);
			lcd_buf[24] = 0xDF;

			//show current temperatures
			U8 *buf = &lcd_buf[32];
			for (U8 i=0; i<4; i++) {
				buf++;// = 0xDF;
				*buf++ = '1' + i;
				*buf++ = ' ';
				S16 t = t_tc[i];
				buf += 4;
				//show temperature or '---' if TC not connected
				if (!t_is_ok(t)) *buf = '-';//memset(buf-2, '-', 3);
				else NUM2ASC_S32(t, buf, 5, 2, 1, 1);
				buf++;
			}
		}
		PT_YIELD(pt);
	}
	PT_END(pt);
}

