mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
91 lines
2.4 KiB
C
91 lines
2.4 KiB
C
/*
|
|
* Copyright (C) 2020 HAW Hamburg
|
|
*
|
|
* This file is subject to the terms and conditions of the GNU Lesser
|
|
* General Public License v2.1. See the file LICENSE in the top level
|
|
* directory for more details.
|
|
*/
|
|
/**
|
|
* @ingroup sys_entropy_source_adc
|
|
*
|
|
* @{
|
|
* @file
|
|
*
|
|
* @author Peter Kietzmann <peter.kietzmann@haw-hamburg.de>
|
|
*
|
|
* @}
|
|
*/
|
|
|
|
#include "periph/adc.h"
|
|
#include "entropy_source.h"
|
|
#include "entropy_source/adc_noise.h"
|
|
|
|
entropy_source_tests_rep_t adc_state_rep;
|
|
entropy_source_tests_prop_t adc_state_prop;
|
|
|
|
static int _get_sample(uint8_t *out)
|
|
{
|
|
int ret = ENTROPY_SOURCE_OK;
|
|
uint8_t byte = 0;
|
|
|
|
for (unsigned bit = 0; bit < 8; bit++) {
|
|
int sample = adc_sample(CONFIG_ENTROPY_SOURCE_ADC_LINE,
|
|
CONFIG_ENTROPY_SOURCE_ADC_RES);
|
|
if (sample < 0) {
|
|
/* Resolution is not applicable */
|
|
return ENTROPY_SOURCE_ERR_CONFIG;
|
|
}
|
|
/* use LSB of each ADC sample and shift it to build a value */
|
|
byte |= (uint8_t)(sample & 0x01) << bit;
|
|
}
|
|
/* copy generated byte to out */
|
|
*out = byte;
|
|
|
|
if (IS_ACTIVE(CONFIG_ENTROPY_SOURCE_ADC_HEALTH_TEST)) {
|
|
ret = entropy_source_test(&adc_state_rep, &adc_state_prop, byte);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int entropy_source_adc_init(void)
|
|
{
|
|
/* init ADC */
|
|
if (adc_init(CONFIG_ENTROPY_SOURCE_ADC_LINE) != 0) {
|
|
return ENTROPY_SOURCE_ERR_INIT;
|
|
}
|
|
|
|
if (IS_ACTIVE(CONFIG_ENTROPY_SOURCE_ADC_HEALTH_TEST)) {
|
|
unsigned int cutoff;
|
|
cutoff = entropy_source_test_rep_cutoff(CONFIG_ENTROPY_SOURCE_ADC_HMIN);
|
|
entropy_source_test_rep_init(&adc_state_rep, cutoff);
|
|
cutoff = entropy_source_test_prop_cutoff(CONFIG_ENTROPY_SOURCE_ADC_HMIN);
|
|
entropy_source_test_prop_init(&adc_state_prop, cutoff);
|
|
}
|
|
|
|
return ENTROPY_SOURCE_OK;
|
|
}
|
|
|
|
int entropy_source_adc_get(uint8_t *out, size_t len)
|
|
{
|
|
assert(out != NULL);
|
|
|
|
int ret = ENTROPY_SOURCE_OK;
|
|
|
|
if (IS_ACTIVE(CONFIG_ENTROPY_SOURCE_ADC_COND)) {
|
|
entropy_source_sample_func_t p = &_get_sample;
|
|
ret = entropy_source_neumann_unbias(p, out, len);
|
|
}
|
|
else {
|
|
for (unsigned iter = 0; iter < len; iter++) {
|
|
int tmp = _get_sample(&out[iter]);
|
|
/* Remember the worst failure during
|
|
* sampling multiple values to return */
|
|
if (tmp < ret) {
|
|
ret = tmp;
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|