/* 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 . */ #include #include #include #include #include #include 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 }, };