gpio.c 3.5 KB
Newer Older
1
2
3
#include "epicardium.h"
#include "gpio.h"
#include "max32665.h"
4
5
#include "mxc_sys.h"
#include "adc.h"
6
#include "mxc_errors.h"
7
8
#include "modules/log.h"
#include "modules/modules.h"
9
10
11
12
13
14

/*
 * Despite what the schematic (currently, 2019-08-18) says these are the correct
 * pins for wristband GPIO 1-4 (not 0-3 as the schematic states)
 */
static gpio_cfg_t gpio_configs[] = {
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
	[EPIC_GPIO_WRISTBAND_1] = { PORT_0,
				    PIN_21,
				    GPIO_FUNC_OUT,
				    GPIO_PAD_NONE },
	[EPIC_GPIO_WRISTBAND_2] = { PORT_0,
				    PIN_22,
				    GPIO_FUNC_OUT,
				    GPIO_PAD_NONE },
	[EPIC_GPIO_WRISTBAND_3] = { PORT_0,
				    PIN_29,
				    GPIO_FUNC_OUT,
				    GPIO_PAD_NONE },
	[EPIC_GPIO_WRISTBAND_4] = { PORT_0,
				    PIN_20,
				    GPIO_FUNC_OUT,
				    GPIO_PAD_NONE },
31
32
};

33
34
35
36
37
38
39
40
41
42
43
static int s_adc_channels[] = {
	[EPIC_GPIO_WRISTBAND_1] = ADC_CH_5,
	[EPIC_GPIO_WRISTBAND_2] = ADC_CH_6,
	/* on P0.29, there is no ADC available
	 * see GPIO matrix in MAX32665-MAX32668.pdf,
	 * pages 32,33
	 */
	[EPIC_GPIO_WRISTBAND_3] = -1,
	[EPIC_GPIO_WRISTBAND_4] = ADC_CH_4,
};

44
45
int epic_gpio_set_pin_mode(uint8_t pin, uint8_t mode)
{
46
	if (pin < EPIC_GPIO_WRISTBAND_1 || pin > EPIC_GPIO_WRISTBAND_4)
47
48
49
50
		return -EINVAL;

	gpio_cfg_t *cfg = &gpio_configs[pin];

51
	if (mode & EPIC_GPIO_MODE_IN) {
52
		cfg->func = GPIO_FUNC_IN;
53
		if (mode & EPIC_GPIO_MODE_OUT) {
54
55
			return -EINVAL;
		}
56
	} else if (mode & EPIC_GPIO_MODE_OUT) {
57
		cfg->func = GPIO_FUNC_OUT;
58
		if (mode & EPIC_GPIO_MODE_IN) {
59
60
			return -EINVAL;
		}
61
62
63
64
65
66
67
68
69
	} else if (mode & EPIC_GPIO_MODE_ADC) {
		if (s_adc_channels[pin] == -1) {
			LOG_WARN("gpio", "ADC not available on pin %d", pin);
			return -EINVAL;
		}
		cfg->func = GPIO_FUNC_ALT1;
		if (mode & EPIC_GPIO_MODE_OUT) {
			return -EINVAL;
		}
70
	} else {
71
		return -EINVAL;
72
	}
73

74
75
76
77
78
79
80
81
	if (!(mode & EPIC_GPIO_MODE_ADC)) {
		if (mode & EPIC_GPIO_PULL_UP) {
			cfg->pad = GPIO_PAD_PULL_UP;
		} else if (mode & EPIC_GPIO_PULL_DOWN) {
			cfg->pad = GPIO_PAD_PULL_DOWN;
		} else {
			cfg->pad = GPIO_PAD_NONE;
		}
82
83
84
	} else {
		cfg->pad = GPIO_PAD_NONE;
	}
85
86
87
88
89
90
91
92

	if (GPIO_Config(cfg) != E_NO_ERROR)
		return -EINVAL;
	return 0;
}

int epic_gpio_get_pin_mode(uint8_t pin)
{
93
	if (pin < EPIC_GPIO_WRISTBAND_1 || pin > EPIC_GPIO_WRISTBAND_4)
94
95
96
97
		return -EINVAL;

	gpio_cfg_t *cfg = &gpio_configs[pin];
	int res         = 0;
98
	if (cfg->func == GPIO_FUNC_IN)
99
		res |= EPIC_GPIO_MODE_IN;
100
	else if (cfg->func == GPIO_FUNC_OUT)
101
		res |= EPIC_GPIO_MODE_OUT;
102
103
	else if (cfg->func == GPIO_FUNC_ALT1)
		res |= EPIC_GPIO_MODE_ADC;
104
	if (cfg->pad == GPIO_PAD_PULL_UP)
105
		res |= EPIC_GPIO_PULL_UP;
106
	else if (cfg->pad == GPIO_PAD_PULL_DOWN)
107
		res |= EPIC_GPIO_PULL_DOWN;
108
109
110
111
112
113

	return res;
}

int epic_gpio_write_pin(uint8_t pin, bool on)
{
114
	if (pin < EPIC_GPIO_WRISTBAND_1 || pin > EPIC_GPIO_WRISTBAND_4)
115
116
117
		return -EINVAL;

	gpio_cfg_t *cfg = &gpio_configs[pin];
118
	if (cfg->func == GPIO_FUNC_IN)
119
120
121
122
123
124
125
126
127
128
		return -EINVAL;

	if (on)
		GPIO_OutSet(cfg);
	else
		GPIO_OutClr(cfg);

	return 0;
}

129
int epic_gpio_read_pin(uint8_t pin)
130
{
131
	if (pin < EPIC_GPIO_WRISTBAND_1 || pin > EPIC_GPIO_WRISTBAND_4)
132
133
134
		return -EINVAL;

	gpio_cfg_t *cfg = &gpio_configs[pin];
135
136
137
138
	if (cfg->func == GPIO_FUNC_OUT) {
		return GPIO_OutGet(cfg) != 0;
	} else if (cfg->func == GPIO_FUNC_IN) {
		return GPIO_InGet(cfg) != 0;
139
140
141
142
143
144
145
146
147
148
149
150
151
	} else if (cfg->func == GPIO_FUNC_ALT1) {
		int rc = hwlock_acquire(HWLOCK_ADC, pdMS_TO_TICKS(10));
		if (!rc) {
			ADC_StartConvert(s_adc_channels[pin], 0, 0);
			uint16_t value;
			int rc = ADC_GetData(&value);
			hwlock_release(HWLOCK_ADC);
			if (rc < 0) {
				return -EIO;
			}
			return (int)value;
		}
		return rc;
152
153
154
155
	} else {
		return -EINVAL;
	}
}