1 /*
2  * Copyright (c) 2023 Nordic Semiconductor ASA
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 
6 #include <stdlib.h>
7 
8 #include <zephyr/device.h>
9 #include <zephyr/drivers/gpio.h>
10 #include <zephyr/drivers/regulator.h>
11 #include <zephyr/drivers/sensor.h>
12 #include <zephyr/drivers/sensor/npm1300_charger.h>
13 #include <zephyr/drivers/led.h>
14 #include <zephyr/dt-bindings/regulator/npm1300.h>
15 #include <zephyr/drivers/mfd/npm1300.h>
16 #include <zephyr/sys/printk.h>
17 #include <getopt.h>
18 
19 #define SLEEP_TIME_MS  100
20 #define UPDATE_TIME_MS 2000
21 
22 static const struct gpio_dt_spec button1 = GPIO_DT_SPEC_GET(DT_ALIAS(sw0), gpios);
23 
24 static const struct device *regulators = DEVICE_DT_GET(DT_NODELABEL(npm1300_ek_regulators));
25 
26 static const struct device *charger = DEVICE_DT_GET(DT_NODELABEL(npm1300_ek_charger));
27 
28 static const struct device *leds = DEVICE_DT_GET(DT_NODELABEL(npm1300_ek_leds));
29 
30 static const struct device *pmic = DEVICE_DT_GET(DT_NODELABEL(npm1300_ek_pmic));
31 
configure_ui(void)32 void configure_ui(void)
33 {
34 	int ret;
35 
36 	if (!gpio_is_ready_dt(&button1)) {
37 		printk("Error: button device %s is not ready\n", button1.port->name);
38 		return;
39 	}
40 
41 	ret = gpio_pin_configure_dt(&button1, GPIO_INPUT);
42 	if (ret != 0) {
43 		printk("Error %d: failed to configure %s pin %d\n", ret, button1.port->name,
44 		       button1.pin);
45 		return;
46 	}
47 
48 	printk("Set up button at %s pin %d\n", button1.port->name, button1.pin);
49 
50 	if (!device_is_ready(leds)) {
51 		printk("Error: led device is not ready\n");
52 		return;
53 	}
54 }
55 
event_callback(const struct device * dev,struct gpio_callback * cb,uint32_t pins)56 static void event_callback(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
57 {
58 	printk("Event detected\n");
59 }
60 
configure_events(void)61 void configure_events(void)
62 {
63 	if (!device_is_ready(pmic)) {
64 		printk("Pmic device not ready.\n");
65 		return;
66 	}
67 
68 	/* Setup callback for shiphold button press */
69 	static struct gpio_callback event_cb;
70 
71 	gpio_init_callback(&event_cb, event_callback, BIT(NPM1300_EVENT_SHIPHOLD_PRESS));
72 
73 	mfd_npm1300_add_callback(pmic, &event_cb);
74 }
75 
read_sensors(void)76 void read_sensors(void)
77 {
78 	struct sensor_value volt;
79 	struct sensor_value current;
80 	struct sensor_value temp;
81 	struct sensor_value error;
82 	struct sensor_value status;
83 	struct sensor_value vbus_present;
84 
85 	sensor_sample_fetch(charger);
86 	sensor_channel_get(charger, SENSOR_CHAN_GAUGE_VOLTAGE, &volt);
87 	sensor_channel_get(charger, SENSOR_CHAN_GAUGE_AVG_CURRENT, &current);
88 	sensor_channel_get(charger, SENSOR_CHAN_GAUGE_TEMP, &temp);
89 	sensor_channel_get(charger, (enum sensor_channel)SENSOR_CHAN_NPM1300_CHARGER_STATUS,
90 			   &status);
91 	sensor_channel_get(charger, (enum sensor_channel)SENSOR_CHAN_NPM1300_CHARGER_ERROR, &error);
92 	sensor_attr_get(charger, (enum sensor_channel)SENSOR_CHAN_NPM1300_CHARGER_VBUS_STATUS,
93 			(enum sensor_attribute)SENSOR_ATTR_NPM1300_CHARGER_VBUS_PRESENT,
94 			&vbus_present);
95 
96 	printk("V: %d.%03d ", volt.val1, volt.val2 / 1000);
97 
98 	printk("I: %s%d.%04d ", ((current.val1 < 0) || (current.val2 < 0)) ? "-" : "",
99 	       abs(current.val1), abs(current.val2) / 100);
100 
101 	printk("T: %s%d.%02d\n", ((temp.val1 < 0) || (temp.val2 < 0)) ? "-" : "", abs(temp.val1),
102 	       abs(temp.val2) / 10000);
103 
104 	printk("Charger Status: %d, Error: %d, VBUS: %s\n", status.val1, error.val1,
105 	       vbus_present.val1 ? "connected" : "disconnected");
106 }
107 
main(void)108 int main(void)
109 {
110 	configure_ui();
111 
112 	configure_events();
113 
114 	if (!device_is_ready(regulators)) {
115 		printk("Error: Regulator device is not ready\n");
116 		return 0;
117 	}
118 
119 	if (!device_is_ready(charger)) {
120 		printk("Charger device not ready.\n");
121 		return 0;
122 	}
123 
124 	while (1) {
125 		/* Cycle regulator control GPIOs when first button pressed */
126 		static bool last_button;
127 		static int dvs_state;
128 		bool button_state = gpio_pin_get_dt(&button1) == 1;
129 
130 		if (button_state && !last_button) {
131 			dvs_state = (dvs_state + 1) % 4;
132 			regulator_parent_dvs_state_set(regulators, dvs_state);
133 		}
134 
135 		/* Update PMIC LED if button state has changed */
136 		if (button_state != last_button) {
137 			if (button_state) {
138 				led_on(leds, 2U);
139 			} else {
140 				led_off(leds, 2U);
141 			}
142 		}
143 
144 		/* Read and display charger status */
145 		static int count;
146 
147 		if (++count > (UPDATE_TIME_MS / SLEEP_TIME_MS)) {
148 			read_sensors();
149 			count = 0;
150 		}
151 
152 		last_button = button_state;
153 		k_msleep(SLEEP_TIME_MS);
154 	}
155 }
156