#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// DHT22 sensor simulation
// This chip simulates a DHT22 temperature and humidity sensor
// Global variables to store temperature and humidity values
float temperature = 25.0; // Default temperature in Celsius
float humidity = 50.0; // Default humidity in percentage
// Function to generate random fluctuations for more realistic readings
float add_fluctuation(float value, float min_fluctuation, float max_fluctuation) {
float fluctuation = min_fluctuation + ((float)rand() / (float)RAND_MAX) * (max_fluctuation - min_fluctuation);
return value + fluctuation;
}
// Initialize the sensor
void chip_init() {
// Seed the random number generator
srand(time(NULL));
// Initialize with slightly randomized values
temperature = add_fluctuation(temperature, -2.0, 2.0);
humidity = add_fluctuation(humidity, -5.0, 5.0);
printf("DHT22 sensor initialized. Initial values: Temperature=%.1f°C, Humidity=%.1f%%\n",
temperature, humidity);
}
// Timer to track when to update values
static unsigned long last_update_time = 0;
// Process incoming commands and update sensor values every second
void chip_tick() {
unsigned long current_time = time(NULL);
// Only update values once per second
if (current_time - last_update_time >= 1) {
// Store previous values for change calculation
float prev_temperature = temperature;
float prev_humidity = humidity;
// Update sensor values with random fluctuations (max 2-3 difference)
temperature = add_fluctuation(temperature, -2.0, 2.0);
// Keep temperature in a realistic range
if (temperature < -10.0) temperature = -10.0;
if (temperature > 50.0) temperature = 50.0;
humidity = add_fluctuation(humidity, -2.0, 2.0);
// Keep humidity in valid range (0-100%)
if (humidity < 0.0) humidity = 0.0;
if (humidity > 100.0) humidity = 100.0;
// Print the updated values and their changes
printf("DHT22 sensor updated: Temperature=%.1f°C (change: %.1f), Humidity=%.1f%% (change: %.1f)\n",
temperature, temperature - prev_temperature,
humidity, humidity - prev_humidity);
// Update the last update time
last_update_time = current_time;
}
}
// Global variables to track communication state
static uint8_t data_buffer[5]; // DHT22 sends 5 bytes of data
static int state = 0;
static int bit_counter = 0;
static int last_value = 1;
static unsigned long last_change_time = 0;
// Prepare the data buffer with current temperature and humidity values
void prepare_data_buffer() {
// Convert temperature and humidity to the format DHT22 would send
uint16_t humid_int = (uint16_t)(humidity * 10);
uint16_t temp_int = (uint16_t)(temperature * 10);
// DHT22 sends negative temperatures with the MSB set in the temperature word
if (temperature < 0) {
temp_int = (uint16_t)(-temperature * 10);
temp_int |= 0x8000; // Set the sign bit
}
// Fill the data buffer
data_buffer[0] = humid_int >> 8; // Humidity high byte
data_buffer[1] = humid_int & 0xFF; // Humidity low byte
data_buffer[2] = temp_int >> 8; // Temperature high byte
data_buffer[3] = temp_int & 0xFF; // Temperature low byte
data_buffer[4] = (data_buffer[0] + data_buffer[1] + data_buffer[2] + data_buffer[3]) & 0xFF; // Checksum
}
// Handle data requests
uint8_t chip_read_pin(uint8_t pin) {
// Only respond on the DATA pin
if (pin != 1) return 0;
// Default to HIGH when idle
if (state == 0) {
return 1;
}
// State machine to simulate DHT22 protocol
switch (state) {
case 1: // Host start signal detected, respond with LOW for 80µs
return 0;
case 2: // Response signal HIGH for 80µs
return 1;
case 3: // Data transmission
if (bit_counter < 40) { // 40 bits of data (5 bytes)
// Each bit starts with a 50µs LOW pulse
if (last_value == 1) {
last_value = 0;
return 0;
} else {
// Followed by a HIGH pulse - 26-28µs for '0', 70µs for '1'
last_value = 1;
// Get the current bit
int byte_index = bit_counter / 8;
int bit_index = 7 - (bit_counter % 8); // MSB first
int bit_value = (data_buffer[byte_index] >> bit_index) & 0x01;
bit_counter++;
return 1; // Return HIGH - the DHT library measures the duration
}
} else {
// All bits sent, go back to idle
state = 0;
bit_counter = 0;
last_value = 1;
return 1;
}
default:
return 1; // Default to HIGH
}
}
// Return sensor data when requested
void chip_write_pin(uint8_t pin, uint8_t value) {
// Only respond to the DATA pin
if (pin != 1) return;
unsigned long current_time = time(NULL);
// Detect start signal (pin goes from HIGH to LOW)
if (value == 0 && last_value == 1) {
// Host is starting communication
state = 1;
last_change_time = current_time;
last_value = value;
// Prepare fresh data
prepare_data_buffer();
printf("DHT22 received start signal. Current readings: Temperature=%.1f°C, Humidity=%.1f%%\n",
temperature, humidity);
}
// Detect end of start signal (pin goes from LOW to HIGH)
else if (value == 1 && last_value == 0) {
// Host has finished the start signal, now we respond
if (state == 1) {
state = 2; // Move to response state
// After a short delay, move to data transmission state
if (current_time - last_change_time >= 1) {
state = 3;
bit_counter = 0;
last_value = 1; // Start with HIGH
}
}
last_change_time = current_time;
last_value = value;
}
}