Skip to content

Commit 007b72b

Browse files
authored
Merge pull request #25 from jancumps/feature-set-2
Feature set 2 thank you @shabaz123
2 parents 90d9d52 + d11a68f commit 007b72b

12 files changed

+403
-24
lines changed

CMakeLists.txt

+8-2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ add_executable(pico_scpi_usbtmc_labtool
2626
${CMAKE_CURRENT_SOURCE_DIR}/source/usb/usbtmc_app.c
2727
${CMAKE_CURRENT_SOURCE_DIR}/source/scpi/scpi-def.c
2828
${CMAKE_CURRENT_SOURCE_DIR}/source/gpio/gpio_utils.c
29+
${CMAKE_CURRENT_SOURCE_DIR}/source/adc/adc_utils.c
30+
${CMAKE_CURRENT_SOURCE_DIR}/source/adc16/adc16_utils.c
31+
${CMAKE_CURRENT_SOURCE_DIR}/source/pwm/pwm_utils.c
2932
$ENV{SCPI_LIB_PATH}/src/parser.c
3033
$ENV{SCPI_LIB_PATH}/src/lexer.c
3134
$ENV{SCPI_LIB_PATH}/src/error.c
@@ -34,17 +37,20 @@ add_executable(pico_scpi_usbtmc_labtool
3437
$ENV{SCPI_LIB_PATH}/src/utils.c
3538
$ENV{SCPI_LIB_PATH}/src/units.c
3639
$ENV{SCPI_LIB_PATH}/src/fifo.c
37-
)
40+
source/adc16/adc16_utils.c source/adc16/adc16_utils.h)
3841

3942
target_include_directories(pico_scpi_usbtmc_labtool PRIVATE
4043
${CMAKE_CURRENT_LIST_DIR}/source
4144
${CMAKE_CURRENT_LIST_DIR}/source/usb
4245
${CMAKE_CURRENT_LIST_DIR}/source/scpi
4346
${CMAKE_CURRENT_LIST_DIR}/source/gpio
47+
${CMAKE_CURRENT_LIST_DIR}/source/adc
48+
${CMAKE_CURRENT_LIST_DIR}/source/adc16
49+
${CMAKE_CURRENT_LIST_DIR}/source/pwm
4450
$ENV{SCPI_LIB_PATH}/inc
4551
)
4652

47-
target_link_libraries(pico_scpi_usbtmc_labtool PUBLIC pico_stdlib tinyusb_device tinyusb_board)
53+
target_link_libraries(pico_scpi_usbtmc_labtool PUBLIC pico_stdlib tinyusb_device tinyusb_board hardware_gpio hardware_adc hardware_pwm hardware_i2c)
4854
pico_add_extra_outputs(pico_scpi_usbtmc_labtool)
4955

5056
# usb output, uart output

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ If you use VSCode: Preferences -> User -> Extensions -> CMake Tools -> CMake: Co
1212
PICO_SDK_PATH (e.g.: C:/Users/jancu/Documents/Pico/pico-sdk)
1313
SCPI_LIB_PATH (e.g.: C:/Users/jancu/Documents/elektronica/scpi/scpi-parser/libscpi)
1414

15+
[documentation](https://github.com/jancumps/pico_scpi_usbtmc_labtool/wiki) on GitHub wiki

source/adc/adc_utils.c

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#include "hardware/adc.h"
2+
3+
#include "adc_utils.h"
4+
5+
/*
6+
ADC0 GP26
7+
ADC1 GP27 // used for button on the pico-eurocard
8+
ADC2 GP28
9+
*/
10+
11+
// supported pins
12+
uint adcPins[][2] = {
13+
{0,26},
14+
// {1,27}, // this is used for the button on the eurocard.
15+
{2,28}
16+
};
17+
18+
void initAdcUtils() {
19+
adc_init();
20+
}
21+
22+
uint32_t adcPinCount() {
23+
return sizeof(adcPins)/(sizeof(adcPins[0][0])+sizeof(adcPins[0][1]));
24+
}
25+
26+
void initAdcPins() {
27+
for (uint32_t i = 0; i < adcPinCount(); i++) {
28+
adc_gpio_init(adcPins[i][1]); // the gpio pin is needed here
29+
}
30+
}
31+
32+
uint16_t getAdcPinAt(uint32_t index) {
33+
adc_select_input(adcPins[index][0]); // the ADC pin number is needed here
34+
return adc_read();
35+
}

source/adc/adc_utils.h

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#ifndef _ADC_UTILS_H
2+
#define _ADC_UTILS_H
3+
4+
void initAdcUtils();
5+
uint32_t adcPinCount();
6+
void initAdcPins();
7+
uint16_t getAdcPinAt(uint32_t index);
8+
9+
#endif // _ADC_UTILS_H

source/adc16/adc16_utils.c

+137
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
#include "adc16_utils.h"
2+
#include "hardware/gpio.h"
3+
#include "hardware/i2c.h"
4+
5+
6+
/*
7+
ADC16 uses the I2C bus to communicate with the ASD1115 chip.
8+
The I2C bus is connected to the following pins:
9+
SCL: GP5
10+
SDA: GP4
11+
12+
ADC strategy:
13+
The ADC is run in continuous-conversion mode. Currently only single-ended inputs are supported,
14+
enumerated as channels 0-3. The ADC is configured to measure +2.048V full-scale, at a rate of 32 SPS,
15+
i.e. a new result is available every 31.25ms. Note: when switching channels, the new result won't be
16+
available for about 80 msec (2 * 31.25ms, plus a small margin).
17+
In single-ended mode, the raw result is a 15-bit value, i.e. 0-32767.
18+
To convert to a voltage, the reported raw result can be multiplied by 2.048/32767.
19+
*/
20+
21+
/************** global vars ***************/
22+
uint8_t adc16Installed = 0;
23+
uint32_t adc16Channel = 0;
24+
uint8_t confreg[2]; // config register
25+
26+
/************** functions *****************/
27+
// initialize the I2C bus
28+
void initAdc16I2C(void) {
29+
i2c_init(i2c_default, 10000); // I2C0 on GPIO 4[SDA],5[SCL]
30+
gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C);
31+
gpio_set_function(PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C);
32+
gpio_pull_up(PICO_DEFAULT_I2C_SDA_PIN); // weak pull-ups but enable them anyway
33+
gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN);
34+
}
35+
36+
// initialize the ADS1115 registers
37+
void initAdc16Reg(void) {
38+
uint8_t buf[3];
39+
// is the ADC chip installed?
40+
buf[0] = ADS1115_REG_CONFIG;
41+
i2c_write_blocking(i2c_default, ADS_ADDR, buf, 1, false);
42+
i2c_read_blocking(i2c_default, ADS_ADDR, buf, 2, false);
43+
if (buf[0] != 0x85 || buf[1] != 0x83) {
44+
adc16Installed = 0; // no chip found
45+
return;
46+
} else {
47+
adc16Installed = 1; // chip found
48+
}
49+
// set config register to desired values
50+
confreg[0] = 0x44; // MUX set to AIN0, and PGA set to +-2.048V and continuous conversion mode
51+
confreg[1] = 0x43; // rate = 32 SPS
52+
buf[0] = ADS1115_REG_CONFIG;
53+
buf[1] = confreg[0];
54+
buf[2] = confreg[1];
55+
i2c_write_blocking(i2c_default, ADS_ADDR, buf, 3, false);
56+
}
57+
58+
// set the multiplexer to the desired input
59+
void setAdc16Mux(uint8_t mux) {
60+
uint8_t buf[3];
61+
confreg[0] &= ~0x70; // clear the MUX bits
62+
confreg[0] |= (mux<<4); // set the MUX bits
63+
buf[0] = ADS1115_REG_CONFIG;
64+
buf[1] = confreg[0];
65+
buf[2] = confreg[1];
66+
i2c_write_blocking(i2c_default, ADS_ADDR, buf, 3, false);
67+
}
68+
69+
// start a conversion (this is only for single-shot mode)
70+
// will delete this function if it's not needed
71+
void startAdc16Conv(void) {
72+
uint8_t buf[3];
73+
buf[0] = ADS1115_REG_CONFIG;
74+
buf[1] = confreg[0] | 0x80; // set 'OS' bit to start a conversion
75+
buf[2] = confreg[1];
76+
i2c_write_blocking(i2c_default, ADS_ADDR, buf, 3, false);
77+
}
78+
79+
// check if the conversion is complete (this may only work for single-shot mode)
80+
// will delete this function if it's not needed
81+
uint8_t adc16ConvDone(void) {
82+
uint8_t buf[3];
83+
buf[0] = ADS1115_REG_CONFIG;
84+
i2c_write_blocking(i2c_default, ADS_ADDR, buf, 1, false);
85+
i2c_read_blocking(i2c_default, ADS_ADDR, buf, 2, false);
86+
if (buf[0] & 0x80) {
87+
return 0; // conversion not done
88+
} else {
89+
return 1; // conversion done
90+
}
91+
}
92+
93+
// read the conversion register
94+
uint16_t readAdc16Meas(void) {
95+
uint16_t meas;
96+
uint16_t buf;
97+
uint8_t* buf8_ptr = (uint8_t*)&buf;
98+
*buf8_ptr = ADS1115_REG_CONVERSION;
99+
i2c_write_blocking(i2c_default, ADS_ADDR, buf8_ptr, 1, false);
100+
i2c_read_blocking(i2c_default, ADS_ADDR, buf8_ptr, 2, false);
101+
meas = buf>>8 | buf<<8; // swap bytes
102+
if (adc16Channel < 4) {
103+
// we are in single-ended mode. Any integer value less than 0 is invalid
104+
// and since we are dealing with unsigned values, that means that any
105+
// value greater than 32767 is invalid.
106+
if (meas > 32767) {
107+
meas = 0;
108+
}
109+
}
110+
return(meas);
111+
}
112+
113+
// provide a pin count. returns 0 if the ADS1115 is not installed
114+
uint32_t adc16PinCount() {
115+
if (adc16Installed) {
116+
return(4);
117+
} else {
118+
return(0);
119+
}
120+
}
121+
122+
// get ADC result from the ADS1115
123+
uint16_t getAdc16PinAt(uint32_t index) {
124+
uint16_t res;
125+
if (adc16Channel == index) {
126+
// already set to this channel
127+
} else {
128+
// switch channel, and then wait for a conversion to be done
129+
adc16Channel = index;
130+
setAdc16Mux(ADS1115_CH0 + index);
131+
// no need to start conversion, since we are in continuous conversion mode
132+
sleep_ms(80); // wait for conversion to complete. The value should be 2 * (1/SPS) + margin
133+
}
134+
res = readAdc16Meas();
135+
// no need to start another conversion, since we are in continuous conversion mode
136+
return(res);
137+
}

source/adc16/adc16_utils.h

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#ifndef _ADC16_UTILS_H
2+
#define _ADC16_UTILS_H
3+
4+
/********** includes **********/
5+
#include "pico/stdlib.h"
6+
7+
/******* defines *********************/
8+
// ADS1115 ADDR pin set to 0V results in I2C address 0x48
9+
#define ADS_ADDR 0x48
10+
// ADS1115 registers (4)
11+
#define ADS1115_REG_CONVERSION 0x00
12+
#define ADS1115_REG_CONFIG 0x01
13+
#define ADS1115_REG_LO_THRESH 0x02
14+
#define ADS1115_REG_HI_THRESH 0x03
15+
// ADS1115 mux values
16+
#define ADS1115_CH0 0x04
17+
#define ADS1115_CH1 0x05
18+
#define ADS1115_CH2 0x06
19+
#define ADS1115_CH3 0x07
20+
#define ADS1115_DIFF_0_1 0x00
21+
#define ADS1115_DIFF_2_3 0x11
22+
23+
/******* functions *********/
24+
void initAdc16I2C(void);
25+
void initAdc16Reg(void);
26+
uint32_t adc16PinCount();
27+
uint16_t getAdc16PinAt(uint32_t index);
28+
29+
#endif // _ADC16_UTILS_H

source/gpio/gpio_utils.c

+18-12
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,35 @@
44
#include "gpio_utils.h"
55

66
// supported pins
7-
uint pins[] = {
7+
uint outPins[] = {
88
/*PICO_DEFAULT_LED_PIN, removed in this project, because the USBTMC code makes good use of it to show USB status
99
if you want to use this pin, remove the led_blinking_task() */
1010
22, 14, 15};
1111

12+
// TODO input pins
1213

13-
uint32_t pinCount() {
14-
return sizeof(pins)/sizeof(pins[0]);
14+
void initGpioUtils() {
15+
return; // nothing needed
1516
}
1617

17-
void initPins() {
18-
for (uint32_t i = 0; i < pinCount(); i++) {
19-
gpio_init(pins[i]);
20-
gpio_set_dir(pins[i], 1);
21-
gpio_put(pins[i], 0);
18+
uint32_t outPinCount() {
19+
return sizeof(outPins)/sizeof(outPins[0]);
20+
}
21+
22+
void initOutPins() {
23+
for (uint32_t i = 0; i < outPinCount(); i++) {
24+
gpio_init(outPins[i]);
25+
gpio_set_dir(outPins[i], 1);
26+
gpio_put(outPins[i], 0);
2227
}
2328
}
2429

25-
void setPinAt(uint32_t index, bool on) {
26-
gpio_put(pins[index], on);
30+
void setOutPinAt(uint32_t index, bool on) {
31+
gpio_put(outPins[index], on);
2732
}
2833

29-
bool isPinAt(uint32_t index) {
30-
return gpio_get_out_level(pins[index]);
34+
bool isOutPinAt(uint32_t index) {
35+
return gpio_get_out_level(outPins[index]);
3136
}
3237

38+
// TODO input pins

source/gpio/gpio_utils.h

+7-4
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22
#define _GPIO_UTILS_H
33

44

5-
uint32_t pinCount();
6-
void initPins();
7-
void setPinAt(uint32_t index, bool on);
8-
bool isPinAt(uint32_t index);
5+
uint32_t outPinCount();
6+
void initGpioUtils();
7+
void initOutPins();
8+
void setOutPinAt(uint32_t index, bool on);
9+
bool isOutPinAt(uint32_t index);
10+
11+
// TODO gpio input pins
912

1013
#endif // _GPIO_UTILS_H

source/pwm/pwm_utils.c

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#include "hardware/pwm.h"
2+
3+
#include "pwm_utils.h"
4+
5+
void initPwmUtils() {
6+
// TODO pwm_init();
7+
}
8+
9+
uint32_t pwmPinCount() {
10+
// TODO implement
11+
return 0;
12+
}
13+
14+
void initPwmPins() {
15+
// TODO implement
16+
return;
17+
}
18+
19+
void setPwmPinAt(uint32_t index, uint32_t value) {
20+
// TODO implement
21+
return;
22+
}

source/pwm/pwm_utils.h

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#ifndef _PWM_UTILS_H
2+
#define _PWM_UTILS_H
3+
4+
void initPwmUtils();
5+
uint32_t pwmPinCount();
6+
void initPwmPins();
7+
void setPwmPinAt(uint32_t index, uint32_t value);
8+
9+
#endif // _PWM_UTILS_H

0 commit comments

Comments
 (0)