block_atsamx70_afec.c 2.84 KB
Newer Older
Jeroen Vreeken's avatar
Jeroen Vreeken committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/*
	Copyright Jeroen Vreeken (jeroen@vreeken.net), 2018

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.

 */

#include <samx70.h>
#include <afec.h>
#include <pio/samx70.h>
#include <ioport.h>

#include <controller/controller_block.h>
#include <log/log.h>


struct controller_block_private {
	float value;
	uint32_t afecnr;
	uint32_t channel;
	
	float factor;
};

static void afec_calculate(struct controller_block *afec)
{
	struct controller_block_private *priv = afec->private;

	int16_t data = afec_read_conversion_data(priv->afecnr, priv->channel);

	float value = data * priv->factor;

	priv->value = value;
}


static struct controller_block_outterm_list outterms[] = {
	{ "value", CONTROLLER_BLOCK_TERM_FLOAT, offsetof(struct controller_block_private, value) },
	{ NULL },
};



static struct controller_block * block_atsamx70_afec_create(char *name, int argc, va_list ap)
{
	struct controller_block *afec;
	int afec_nr;
	
	afec_nr = va_arg(ap, int);
	if (afec_nr < 0 || afec_nr > 1) {
		log_send(LOG_T_ERROR, "%s: afec%d is not valid. (valid: 0-1)",
		    name, afec_nr);
		return NULL;
	}

	if (!(afec = controller_block_alloc("atsamx70_afec", name, sizeof(struct controller_block_private))))
		goto err_alloc;

	if (controller_block_outterm_list_init(afec, outterms))
		goto err_outterm;

	afec->calculate = afec_calculate;
	
	uint32_t pin;
	
	switch (afec_nr) {
		case 0:
			afec->private->afecnr = AFEC0;
			afec->private->channel = 0;
			pin = PIO_PD30_IDX;
			break;
		case 1:
			afec->private->afecnr = AFEC1;
			afec->private->channel = 1;
			pin = PIO_PC13_IDX;
			break;
	}
	afec->private->factor = 1.0 / 2048.0;
	
	ioport_init();
	
	ioport_disable_pin(pin);

	afec_init(afec->private->afecnr, 
	    AFEC_MR_FREERUN | AFEC_MR_PRESCAL((sysclk_get_peripheral_hz()+AFEC_FMAX-1)/AFEC_FMAX),
	    AFEC_EMR_RES_16 | AFEC_EMR_STM_SINGLE | AFEC_EMR_SIGNMODE_SIGNED);
	afec_channel_set_offset(afec->private->afecnr, 0, (AFEC_ACR_AOFF_MAX+1)/2);
	afec_channel_set_gain(afec->private->afecnr, 0, 0); // set gain to 1 (value 0)

	afec_channel_enable(afec->private->afecnr, afec_nr);

	if (controller_block_add(afec))
		goto err_add;
	return afec;

err_add:
err_outterm:
	controller_block_free(afec);
err_alloc:
	return NULL;
}

BLOCK_CREATE(atsamx70_afec) = {
	.create = block_atsamx70_afec_create,
	.args = { "int", NULL },
};