mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
157 lines
4.2 KiB
C
157 lines
4.2 KiB
C
/* ULP-RISC-V example
|
|
|
|
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
|
|
|
Unless required by applicable law or agreed to in writing, this
|
|
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
This code runs on ULP-RISC-V coprocessor
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#include "ulp_riscv/ulp_riscv.h"
|
|
#include "ulp_riscv/ulp_riscv_utils.h"
|
|
#include "ulp_riscv/ulp_riscv_gpio.h"
|
|
|
|
#define EXAMPLE_1WIRE_GPIO GPIO_NUM_4
|
|
|
|
#define WAKEUP_TEMP_C 32.5
|
|
#define TEMP_ALARM_LIMIT ( (int)(WAKEUP_TEMP_C*16) )
|
|
|
|
typedef enum {
|
|
SENSOR_CONVERSION_INIT,
|
|
SENSOR_CONVERSION_READ,
|
|
} sensor_state_t;
|
|
|
|
sensor_state_t state = SENSOR_CONVERSION_INIT;
|
|
int32_t temp_reg_val = INT32_MIN;
|
|
|
|
static void ds18b20_write_bit(bool bit)
|
|
{
|
|
ulp_riscv_gpio_output_level(EXAMPLE_1WIRE_GPIO, 0);
|
|
if (bit) {
|
|
/* Must pull high within 15 us, without delay this takes 5 us */
|
|
ulp_riscv_gpio_output_level(EXAMPLE_1WIRE_GPIO, 1);
|
|
}
|
|
|
|
/* Write slot duration at least 60 us */
|
|
ulp_riscv_delay_cycles(60 * ULP_RISCV_CYCLES_PER_US);
|
|
ulp_riscv_gpio_output_level(EXAMPLE_1WIRE_GPIO, 1);
|
|
}
|
|
|
|
static bool ds18b20_read_bit(void)
|
|
{
|
|
bool bit;
|
|
|
|
/* Pull low minimum 1 us */
|
|
ulp_riscv_gpio_output_level(EXAMPLE_1WIRE_GPIO, 0);
|
|
ulp_riscv_gpio_output_level(EXAMPLE_1WIRE_GPIO, 1);
|
|
|
|
/* Must sample within 15 us of the failing edge */
|
|
ulp_riscv_delay_cycles(5 * ULP_RISCV_CYCLES_PER_US);
|
|
bit = ulp_riscv_gpio_get_level(EXAMPLE_1WIRE_GPIO);
|
|
|
|
/* Read slot duration at least 60 us */
|
|
ulp_riscv_delay_cycles(55 * ULP_RISCV_CYCLES_PER_US);
|
|
|
|
return bit;
|
|
}
|
|
|
|
static void ds18b20_write_byte(uint8_t data)
|
|
{
|
|
for (int i = 0; i < 8; i++) {
|
|
ds18b20_write_bit((data >> i) & 0x1);
|
|
}
|
|
}
|
|
|
|
static uint8_t ds18b20_read_byte(void)
|
|
{
|
|
uint8_t data = 0;
|
|
for (int i = 0; i < 8; i++) {
|
|
data |= ds18b20_read_bit() << i;
|
|
}
|
|
return data;
|
|
}
|
|
|
|
bool ds18b20_reset_pulse(void)
|
|
{
|
|
bool presence_pulse;
|
|
/* min 480 us reset pulse + 480 us reply time is specified by datasheet */
|
|
ulp_riscv_gpio_output_level(EXAMPLE_1WIRE_GPIO, 0);
|
|
ulp_riscv_delay_cycles(480 * ULP_RISCV_CYCLES_PER_US);
|
|
|
|
ulp_riscv_gpio_output_level(EXAMPLE_1WIRE_GPIO, 1);
|
|
|
|
/* Wait for ds18b20 to pull low before sampling */
|
|
ulp_riscv_delay_cycles(60 * ULP_RISCV_CYCLES_PER_US);
|
|
presence_pulse = ulp_riscv_gpio_get_level(EXAMPLE_1WIRE_GPIO) == 0;
|
|
|
|
ulp_riscv_delay_cycles(420 * ULP_RISCV_CYCLES_PER_US);
|
|
|
|
return presence_pulse;
|
|
}
|
|
|
|
int main (void)
|
|
{
|
|
uint8_t temp_high_byte;
|
|
uint8_t temp_low_byte;
|
|
|
|
/* Setup GPIO used for 1wire */
|
|
ulp_riscv_gpio_init(EXAMPLE_1WIRE_GPIO);
|
|
ulp_riscv_gpio_input_enable(EXAMPLE_1WIRE_GPIO);
|
|
ulp_riscv_gpio_output_enable(EXAMPLE_1WIRE_GPIO);
|
|
ulp_riscv_gpio_set_output_mode(EXAMPLE_1WIRE_GPIO, RTCIO_MODE_OUTPUT_OD);
|
|
ulp_riscv_gpio_pullup(EXAMPLE_1WIRE_GPIO);
|
|
ulp_riscv_gpio_pulldown_disable(EXAMPLE_1WIRE_GPIO);
|
|
|
|
|
|
switch (state) {
|
|
case SENSOR_CONVERSION_INIT:
|
|
if (!ds18b20_reset_pulse()) {
|
|
temp_reg_val = INT32_MIN;
|
|
break;
|
|
}
|
|
/* Start conversion */
|
|
ds18b20_write_byte(0xCC);
|
|
ds18b20_write_byte(0x44);
|
|
|
|
/* shutdown and wait for next period (750ms) where the data is ready for reading */
|
|
state = SENSOR_CONVERSION_READ;
|
|
break;
|
|
|
|
case SENSOR_CONVERSION_READ:
|
|
if (!ds18b20_reset_pulse()) {
|
|
temp_reg_val = INT32_MIN;
|
|
state = SENSOR_CONVERSION_INIT;
|
|
break;
|
|
}
|
|
|
|
/* Read scratchpad */
|
|
ds18b20_write_byte(0xCC);
|
|
ds18b20_write_byte(0xBE);
|
|
|
|
temp_low_byte = ds18b20_read_byte();
|
|
temp_high_byte = ds18b20_read_byte();
|
|
|
|
temp_reg_val = temp_high_byte << 8;
|
|
temp_reg_val |= temp_low_byte;
|
|
state = SENSOR_CONVERSION_INIT;
|
|
|
|
/* Wakes up the main CPU if the temperature exceeds the limit */
|
|
if (temp_reg_val > TEMP_ALARM_LIMIT) {
|
|
ulp_riscv_wakeup_main_processor();
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
/* ulp_riscv_shutdown() is called automatically when main exits,
|
|
main will be executed again at the next timeout period,
|
|
according to ulp_set_wakeup_period()
|
|
*/
|
|
return 0;
|
|
}
|