/**
 * \file adc_subsystem.c
 * \brief 内蔵ADC制御関数
 * \date 2011/02/19
 * \author Takemasa Nakamura
 */

#include "uzume.h"
#include <LPC17xx.h>
#include <lpc17xx_pinsel.h>
#include <lpc17xx_gpio.h>
#include <lpc17xx_adc.h>
#include <lpc17xx_clkpwr.h>
#include <kernel.h>
#include <t_syslog.h>

static	unsigned short values[UZUME_NUM_ADC];


void adc_init()
{
	PINSEL_CFG_Type pincfg;
	CLKPWR_ConfigPPWR( CLKPWR_PCONP_PCAD, ENABLE);

	ADC_Init(LPC_ADC, 200000);

	pincfg.Portnum = 0; 	/* ADC0は port0 */
	pincfg.Pinnum = 23;	/* ADC0.0は pin 23 */
	pincfg.Pinmode = PINSEL_PINMODE_TRISTATE;
	pincfg.OpenDrain = PINSEL_PINMODE_NORMAL;
	pincfg.Funcnum = 1;	/* set to ADC assign */

	PINSEL_ConfigPin(&pincfg);

	pincfg.Pinnum = 24;	/* ADC0.1は pin 24 */
	PINSEL_ConfigPin(&pincfg);

	pincfg.Pinnum = 25;	/* ADC0.2は pin 25 */
	PINSEL_ConfigPin(&pincfg);

	pincfg.Pinnum = 26;	/* ADC0.3は pin 26 */
	PINSEL_ConfigPin(&pincfg);
}

ADC_SAMPLE adc_read( int ch)
{
		// ADC_getData()で取得したデータは0-4095の範囲をもっている。
		// これを、16bitの正の最大範囲 0-32767に拡張する。
	return ( values[ch] << 3);
}


/*
 *  ADCテストタスク
 *  ADC0-3の値を読み取り、コンソール出力する
 */
void adc_task(intptr_t exinf)
{
	int i;

	syslog(LOG_NOTICE, "ADC task starts ");



	while (1)
	{
			/* ソフトウェアによる変換開始の場合、一度に変換できるのは1チャンネルだけである
			 * したがって、全部のチャンネルをソフトウェアでスキャンする */
		for ( i=0; i<UZUME_NUM_ADC; i++)
		{
				/* チャンネル選択 */
			ADC_ChannelCmd(LPC_ADC,i,ENABLE);
				/* ワンショットの変換開始　*/
			ADC_StartCmd(LPC_ADC, ADC_START_NOW);
				/* 50m秒待つ */
			tslp_tsk(50);
			values[i] = ADC_ChannelGetData(LPC_ADC, i);
				/* チャンネル選択解除 */
			ADC_ChannelCmd(LPC_ADC,i,DISABLE);

		}
		syslog(LOG_NOTICE, "ADC ch 0 : %5d", adc_read(0));
	}


	SVC_PERROR(ext_ker());
	assert(0);
}

