#include <stdio.h>
#include<string.h>
#include<stdlib.h>
#include "soc/uart_struct.h"
#include"freertos/FreeRTOS.h"
#include"freertos/task.h"
#include"esp_system.h"
#include"esp_log.h"
#include"driver/gpio.h"
#include"driver/uart.h"
#include "driver/i2c.h"
#include <sys/unistd.h>
#include <sys/stat.h>
#include "esp_vfs_fat.h"
#include "sdmmc_cmd.h"
///////////////////////////////////////////sd//////////////////////////////////////
#define MOUNT_POINT "/sdcard"
#define PIN_NUM_MISO 2
#define PIN_NUM_MOSI 15
#define PIN_NUM_CLK 14
#define PIN_NUM_CS 13
esp_err_t ret;
sdmmc_card_t *card;
const char mount_point[] = MOUNT_POINT;
sdmmc_host_t host;
sdspi_device_config_t slot_config;
///////////////////////////////////////////gsm//////////////////////////////////////
static const int RX_BUF_SIZE = 1024;
static const char *TX_TASK_TAG = "TX_TASK";
#define TXD_PIN (GPIO_NUM_18)
#define RXD_PIN (GPIO_NUM_19)
/////////////////////////////////////////////gps//////////////////////////////////
//static const int RX_BUF_SIZE =1024;
//UART0
//#define TXD_PIN (GPIO_NUM_18)
//#define RXD_PIN (GPIO_NUM_19)
//UART2
#define TXD_PIN2 (GPIO_NUM_17)
#define RXD_PIN2 (GPIO_NUM_16)
static const char* TAG = "MyModule";
char heure[3]="";
char minute[3]="";
char second[3]="";
char latitude[15];
char longitude[15];
/////////////////////////////////////li7us3dh/////////////////////////////////
#define GPIO_SDA_PIN 21
#define GPIO_SCL_PIN 22
#define INT1_PIN 4
// I2C address of MPU6050
#define I2C_MASTER_FREQ_HZ 100000
#define SAMPLE_PERIOD_MS 200
#define LIS3DH_REG_TEMPCFG 0x1F
#define I2C_MASTER_NUM 0
#define I2C_MASTER_TX_BUF_DISABLE 0
#define I2C_MASTER_RX_BUF_DISABLE 0
#define I2C_MASTER_RX_BUF_ENABLE 1
#define I2C_MASTER_TX_BUF_ENABLE 1
#define LIS3DH_REG_WHOAMI 0x0F
#define ADDR_MODE_WRITE 0x30
#define ADDR_MODE_read 0x31
#define LIS3DH_ADDRESS 0x18
#define LIS3DH_OUT_X_L 0x28
#define low_power_xyz_active_100hz 0xAF
#define High_pass_filter_disabled 0x00
#define Interrupt_activity_1_driven_to_INT1_pad 0x40
#define FS_2 0x00
#define Interrupt_1_pin_latched 0x08
#define free_fall_threshold_350_mg 0x16
#define minimum_event_duration 0x03
#define _free_fall_recognition 0x95
#define INT1_THS 0x32
#define INT1_DURATION 0x33
#define INT1_CFG 0x30
#define CTRL_REG1 0x20
#define CTRL_REG2 0x21
#define CTRL_REG3 0x22
#define CTRL_REG4 0x23
#define CTRL_REG5 0x24
#define INT1_SRC 0x31
typedef struct ACCEL_DATA {
int16_t X;
int16_t Y;
int16_t Z;
} stACCEL_DATA_t;
uint8_t data[6];
static const int16_t msg_queue_len = 9;
static QueueHandle_t msg_queue;
int16_t datax;
int16_t datay;
int16_t dataz;
////////////////////////////////////////////////sd_func/////////////////////////////////////////
static void func(void){
// Options for mounting the filesystem.
// If format_if_mount_failed is set to true, SD card will be partitioned and
// formatted in case when mounting fails.
esp_vfs_fat_sdmmc_mount_config_t mount_config = {
/*#ifdef CONFIG_EXAMPLE_FORMAT_IF_MOUNT_FAILED
.format_if_mount_failed = true,
#else
.format_if_mount_failed = false,
#endif// EXAMPLE_FORMAT_IF_MOUNT_FAILED*/
.max_files = 5,
.allocation_unit_size = 16 * 1024
};
ESP_LOGI(TAG, "Initializing SD card");
// Use settings defined above to initialize SD card and mount FAT filesystem.
// Note: esp_vfs_fat_sdmmc/sdspi_mount is all-in-one convenience functions.
// Please check its source code and implement error recovery when developing
// production applications.
ESP_LOGI(TAG, "Using SPI peripheral");
sdmmc_host_t host = SDSPI_HOST_DEFAULT();
spi_bus_config_t bus_cfg = {
.mosi_io_num = PIN_NUM_MOSI,
.miso_io_num = PIN_NUM_MISO,
.sclk_io_num = PIN_NUM_CLK,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.max_transfer_sz = 4000,
};
ret = spi_bus_initialize(host.slot, &bus_cfg, SDSPI_DEFAULT_HOST);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to initialize bus.");
return;
}
// This initializes the slot without card detect (CD) and write protect (WP) signals.
// Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals.
sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT();
slot_config.gpio_cs = PIN_NUM_CS;
slot_config.host_id = host.slot;
ESP_LOGI(TAG, "Mounting filesystem");
ret = esp_vfs_fat_sdspi_mount(mount_point, &host, &slot_config, &mount_config, &card);
if (ret != ESP_OK) {
if (ret == ESP_FAIL) {
ESP_LOGE(TAG, "Failed to mount filesystem. "
"If you want the card to be formatted, set the CONFIG_EXAMPLE_FORMAT_IF_MOUNT_FAILED menuconfig option.");
} else {
ESP_LOGE(TAG, "Failed to initialize the card (%s). "
"Make sure SD card lines have pull-up resistors in place.", esp_err_to_name(ret));
}
return;
}
ESP_LOGI(TAG, "Filesystem mounted");
// Card has been initialized, print its properties
sdmmc_card_print_info(stdout, card);
}
////////////////////////////////////////////////lis3dh_func////////////////////////////////////////
static void i2c_master_init(void){
int i2c_master_port = I2C_NUM_0;
i2c_config_t conf ={
.mode = I2C_MODE_MASTER,
.sda_io_num = GPIO_SDA_PIN ,
.scl_io_num = GPIO_SCL_PIN ,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = I2C_MASTER_FREQ_HZ,
};
i2c_param_config(i2c_master_port, &conf);
i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
}
uint16_t byte_swap( uint16_t data )
{
return( (data >> 8) | (data << 8));
}
static esp_err_t i2c_master_read_slave_reg(i2c_port_t i2c_num, uint8_t i2c_addr, uint8_t i2c_reg, uint8_t* data_rd, uint8_t size)
{
if (size == 0) {
return ESP_OK;
}
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, ( i2c_addr << 1 ) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(cmd, i2c_reg | 0x80 , true);
i2c_master_start(cmd);
i2c_master_write_byte(cmd, ( i2c_addr << 1 ) | I2C_MASTER_READ, true);
if (size > 1) {
i2c_master_read(cmd, data_rd, size - 1, I2C_MASTER_ACK);
}
i2c_master_read_byte(cmd, data_rd + size - 1, I2C_MASTER_NACK);
i2c_master_stop(cmd);
esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
return ret;
}
esp_err_t rdlis3dh( uint8_t reg, uint8_t *pdata, uint8_t count )
{
return( i2c_master_read_slave_reg( I2C_MASTER_NUM, LIS3DH_ADDRESS, reg, pdata, count ) );
}
static esp_err_t i2c_master_write_slave_reg(i2c_port_t i2c_num, uint8_t i2c_addr, uint8_t i2c_reg, uint8_t* data_wr, uint8_t size)
{
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, ( i2c_addr << 1 ) | I2C_MASTER_WRITE, true);
i2c_master_write_byte(cmd, i2c_reg, true);
i2c_master_write(cmd, data_wr, size, true);
i2c_master_stop(cmd);
esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
return ret;
}
esp_err_t wrlis3dh( uint8_t reg, uint8_t *pdata, uint8_t count )
{
return( i2c_master_write_slave_reg( I2C_MASTER_NUM, LIS3DH_ADDRESS, reg, pdata, count ) );
}
static void lis3dh_init()
{
uint8_t val;
rdlis3dh(LIS3DH_REG_WHOAMI, &(val), 1);
if (val == 0x33) {
ESP_LOGI( TAG, "lis3dh ID:0x%X (ok)", val );
} else {
ESP_LOGE( TAG, "lis3dh ID:0x%X !!!! (NOT correct; should be 0x1A)", val );
}
val = (low_power_xyz_active_100hz);
wrlis3dh (CTRL_REG1,&(val), 1);
val = (High_pass_filter_disabled);
wrlis3dh(CTRL_REG2, &(val), 1 );
val = (Interrupt_activity_1_driven_to_INT1_pad);
wrlis3dh(CTRL_REG3, &(val), 1 );
val = (FS_2);
wrlis3dh(CTRL_REG4, &(val), 1 );
val = (Interrupt_1_pin_latched);
wrlis3dh(CTRL_REG5, &(val), 1 );
val = (free_fall_threshold_350_mg);
wrlis3dh(INT1_THS, &(val), 1 );
val = (minimum_event_duration);
wrlis3dh(INT1_DURATION, &(val), 1 );
val = (_free_fall_recognition);
wrlis3dh(INT1_CFG, &(val), 1 );
val = (_free_fall_recognition);
rdlis3dh( INT1_SRC, &val, 1 );
}
////////////////////////////////////////gps_fun////////////////////////////////////////////////
//init uart 0
/*void init_uart0(void){
const uart_config_t uart_config={
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_APB,
};
uart_driver_install(UART_NUM_1,RX_BUF_SIZE*2,0,0,NULL,0);
uart_param_config(UART_NUM_1, &uart_config);
uart_set_pin(UART_NUM_1, TXD_PIN, RXD_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
}*/
//for uart2
void init_uart2(void){
const uart_config_t uart_config_2={
.baud_rate = 9600,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_APB,
//.rx_flow_ctrl_thresh = 122,
};
uart_driver_install(UART_NUM_2,RX_BUF_SIZE*2,0,0,NULL,0);
uart_param_config(UART_NUM_2, &uart_config_2);
uart_set_pin(UART_NUM_2, TXD_PIN2, RXD_PIN2, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
}
////////////////////////////////////////////////gsm_func////////////////////////////////////
void init_uart1() {
const uart_config_t uart_config = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE
};
uart_param_config(UART_NUM_1, &uart_config);
uart_set_pin(UART_NUM_1, TXD_PIN, RXD_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
// We won't use a buffer for sending data.
uart_driver_install(UART_NUM_1, RX_BUF_SIZE * 2, 0, 0, NULL, 0);
}
int sendData(const char* logName, const char* data)
{
const int len = strlen(data);
const int txBytes = uart_write_bytes(UART_NUM_1, data, len);
ESP_LOGI(logName, "Wrote %d bytes", txBytes);
return txBytes;
}
int readData(){
uint8_t* data = (uint8_t*) malloc(RX_BUF_SIZE+1);
const int rxBytes = uart_read_bytes(UART_NUM_1, data, RX_BUF_SIZE, 1000 / portTICK_RATE_MS);
if (rxBytes > 0) {
data[rxBytes] = 0;
ESP_LOGI(TX_TASK_TAG, "Read %d bytes: '%s'", rxBytes, data);
// ESP_LOG_BUFFER_HEXDUMP(RX_TASK_TAG, data, rxBytes, ESP_LOG_INFO);
}
return(data);
free(data);
}
////////////////////////////////////////////////sd_task/////////////////////////////////////////
static void task(void *arg){
// Use POSIX and C standard library functions to work with files.
// First create a file.
while(1){
const char *file_hello = MOUNT_POINT"/hello.txt";
ESP_LOGI(TAG, "Opening file %s", file_hello);
FILE *f = fopen(file_hello, "a+");
if (f == NULL) {
ESP_LOGE(TAG, "Failed to open file for writing");
return;
}
fprintf(f, "Hello wkhay %s!\n", card->cid.name);
fclose(f);
ESP_LOGI(TAG, "File written");
const char *file_foo = MOUNT_POINT"/foo.txt";
// Check if destination file exists before renaming
struct stat st;
if (stat(file_foo, &st) == 0) {
// Delete it if it exists
unlink(file_foo);
}
// Rename original file
ESP_LOGI(TAG, "Renaming file %s to %s", file_hello, file_foo);
if (rename(file_hello, file_foo) != 0) {
ESP_LOGE(TAG, "Rename failed");
return;
}
// Open renamed file for reading
ESP_LOGI(TAG, "Reading file %s", file_foo);
f = fopen(file_foo, "r");
if (f == NULL) {
ESP_LOGE(TAG, "Failed to open file for reading");
return;
}
// Read a line from file
char line[64];
fgets(line, sizeof(line), f);
fclose(f);
// Strip newline
char *pos = strchr(line, '\n');
if (pos) {
*pos = '\0';
}
ESP_LOGI(TAG, "Read from file: '%s'", line);
vTaskDelay(300000/portTICK_RATE_MS);
}
// All done, unmount partition and disable SPI peripheral
esp_vfs_fat_sdcard_unmount(mount_point, card);
ESP_LOGI(TAG, "Card unmounted");
//deinitialize the bus after all devices are removed
spi_bus_free(host.slot);
}
////////////////////////////////////////////////lis3dh_task/////////////////////////////////////
static void i2c_test_task(void* arg)
{
esp_err_t err;
stACCEL_DATA_t acc;
uint8_t read_data;
uint8_t val;
ESP_LOGI( TAG, "ESP I2C_RESTART Example - lis3dh Accelerometer" );
while (1) {
// Note: as configured, reading data from the output registers will start next acquisition
//err = rdlis3dh( LIS3DH_OUT_X_L, (uint8_t *)&acc, sizeof(acc) );
if(gpio_get_level(INT1_PIN)== 1 ){
printf("zzzzzzzzzzzzzzzzzz");
err = rdlis3dh( LIS3DH_OUT_X_L, &data, sizeof(acc) );
/*
acc.X = byte_swap( acc.X );
acc.Y = byte_swap( acc.Y );
acc.Z = byte_swap( acc.Z );
// shift each value to align 14-bits in 16-bit ints
acc.X /= 4;
acc.Y /= 4;
acc.Z /= 4;
ESP_LOGI( TAG, "Accelerometer err:%d x:%5d y:%5d z:%5d", err, acc.X, acc.Y, acc.Z );
vTaskDelay( pdMS_TO_TICKS( SAMPLE_PERIOD_MS ) );*/
// print data
ESP_LOGI("LIS3DH_DATA", "X: %5d", (int16_t)(data[1] << 8 | data[0]));
ESP_LOGI("LIS3DH_DATA", "Y: %5d", (int16_t)(data[3] << 8 | data[2]));
ESP_LOGI("LIS3DH_DATA", "Z: %5d", (int16_t)(data[5] << 8 | data[4]));
datax=(int16_t)(data[1] << 8 | data[0]);
datay=(int16_t)(data[3] << 8 | data[2]);
dataz=(int16_t)(data[5] << 8 | data[4]);
if(xQueueSend(msg_queue, &datax,10)!= pdTRUE){
ESP_LOGI( TAG, "full" );
}
if(xQueueSend(msg_queue, &datay,10)!= pdTRUE){
ESP_LOGI( TAG, "full" );
}
if(xQueueSend(msg_queue, &dataz,10)!= pdTRUE){
ESP_LOGI( TAG, "full" );
}
rdlis3dh( INT1_SRC, &val, 1 );
}
vTaskDelay(500 / portTICK_RATE_MS);
}
}
///////////////////////////////////////////////gps_task/////////////////////////////////////////////
static void rx_task(void *arg){
char* data = (char*)malloc(RX_BUF_SIZE+1);
while(1){
const int rxbytes = uart_read_bytes(UART_NUM_2,data, RX_BUF_SIZE, 1000/portTICK_RATE_MS);
//printf("data= %d",rxbytes);
if(rxbytes>0){
//printf("data rani dkhalt ");
data[rxbytes] = 0;
// uart_write_bytes(UART_NUM_1, (const char*)data,rxbytes);
char * result = strstr(data,"$GPGGA,");
ESP_LOGI(TAG,"aaaaaaaaaaaaaaaaaaaaaaaaa %s\n",result);
memcpy(heure,&result[0]+7,2);
memcpy(minute,&result[0]+9,2);
memcpy(second,&result[0]+11,2);
memcpy(latitude,&result[0]+17,12);
memcpy(longitude,&result[0]+30,13);
printf("time is %s:%s:%s \n",heure,minute,second);
ESP_LOGI(TAG,"latitude is %s\n",latitude);
ESP_LOGI(TAG,"longitude is %s\n",longitude);
//ESP_LOGI(TAG,"%d",rxbytes);
// ESP_LOG_BUFFER_HEXDUMP(TAG, data, rxbytes, ESP_LOG_INFO);
//ESP_LOG_BUFFER_CHAR_LEVEL(TAG, data, rxbytes, ESP_LOG_INFO);
//ESP_LOG_BUFFER_CHAR(TAG, data, rxbytes);
}
vTaskDelay(300000/portTICK_RATE_MS);
}
free(data);
}
////////////////////////////////////////////////gsm_task/////////////////////////////////////////////////////
static void tx_task(void *paramaters)
{
char dat;
char thingsbuffer[180];
esp_log_level_set(TX_TASK_TAG, ESP_LOG_INFO);
int16_t xdata;
int16_t ydata;
int16_t zdata;
while (1) {
if(xQueueReceive(msg_queue, (void *)&xdata,0) == pdTRUE){
ESP_LOGI( TAG, "lis3dh %5d x ", xdata );
}
if(xQueueReceive(msg_queue, (void *)&ydata,0) == pdTRUE){
ESP_LOGI( TAG, "lis3dh %5d y", ydata );
}
if(xQueueReceive(msg_queue, (void *)&zdata,0) == pdTRUE){
ESP_LOGI( TAG, "lis3dh %5d z ", zdata );
}
sendData(TX_TASK_TAG, "AT\r\n");
// vTaskDelay(pdMS_TO_TICKS(1000));
// readData();
vTaskDelay(pdMS_TO_TICKS(1000));
// uint8_t* dat = readData();
sendData(TX_TASK_TAG, "AT+CPIN?\r\n");
// vTaskDelay(pdMS_TO_TICKS(1000));
// readData();
vTaskDelay(pdMS_TO_TICKS(1000));
sendData(TX_TASK_TAG, "AT+CPIN=0000\r\n");
// vTaskDelay(pdMS_TO_TICKS(1000));
// readData();
vTaskDelay(pdMS_TO_TICKS(10000));
// ESP_LOGI(TX_TASK_TAG, "fefffsssssfsfsfsfsffsfs : %s", dat);
sendData(TX_TASK_TAG, "AT+CIPSHUT\r\n");
vTaskDelay(pdMS_TO_TICKS(400));
readData();
// vTaskDelay(pdMS_TO_TICKS(1000));
sendData(TX_TASK_TAG, "AT+CGATT=1\r\n");
vTaskDelay(pdMS_TO_TICKS(400));
readData();
// vTaskDelay(pdMS_TO_TICKS(1000));
sendData(TX_TASK_TAG, "AT+CIPMUX=0\r\n");
vTaskDelay(pdMS_TO_TICKS(400));
readData();
//vTaskDelay(pdMS_TO_TICKS(1000));
sendData(TX_TASK_TAG, "AT+CSTT=\"www\",\"\",\"\",\r\n");
vTaskDelay(pdMS_TO_TICKS(400));
readData();
// vTaskDelay(pdMS_TO_TICKS(1000));
sendData(TX_TASK_TAG, "AT+CIICR\r\n");
vTaskDelay(pdMS_TO_TICKS(400));
readData();
// vTaskDelay(pdMS_TO_TICKS(1000));
sendData(TX_TASK_TAG, "AT+CIFSR\r\n");
vTaskDelay(pdMS_TO_TICKS(400));
readData();
// vTaskDelay(pdMS_TO_TICKS(1000));
sendData(TX_TASK_TAG, "AT+CIPSTART=\"TCP\",\"184.106.153.149\",80\r\n");
vTaskDelay(pdMS_TO_TICKS(400));
readData();
// vTaskDelay(pdMS_TO_TICKS(1000));
sendData(TX_TASK_TAG, "AT+CIPSEND\r\n");
vTaskDelay(pdMS_TO_TICKS(400));
readData();
// vTaskDelay(pdMS_TO_TICKS(1000));
// sprintf(thingsbuffer,"GET https://api.thingspeak.com/update?api_k ... ,(int16_t)(data[1] << 8 | data[0]),(int16_t)(data[3] << 8 | data[2]),(int16_t)(data[5] << 8 | data[4]));
sprintf(thingsbuffer,"GET https://api.thingspeak.com/update?api_k ... data,zdata);
// sprintf(thingsbuffer,"GET https://api.thingspeak.com/update?api_k ... ,(int16_t)(data[1] << 8 | data[0]),(int16_t)(data[3] << 8 | data[2]),(int16_t)(data[5] << 8 | data[4]));
sendData(TX_TASK_TAG, thingsbuffer);
vTaskDelay(pdMS_TO_TICKS(400));
readData();
// vTaskDelay(pdMS_TO_TICKS(1000));
sendData(TX_TASK_TAG, "\r\n");
vTaskDelay(pdMS_TO_TICKS(400));
readData();
// vTaskDelay(pdMS_TO_TICKS(1000));
sendData(TX_TASK_TAG, "AT+CIPCLOSE\r\n");
vTaskDelay(pdMS_TO_TICKS(400));
readData();
vTaskDelay(6000 / portTICK_PERIOD_MS);
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void app_main(void)
{
//init();
func();
msg_queue = xQueueCreate(msg_queue_len,sizeof(int16_t));
init_uart1();
init_uart2();
i2c_master_init();
ESP_LOGI(TAG, "I2C initialized successfully");
lis3dh_init();
xTaskCreate(rx_task, "uart_rx_task", 1024*2, NULL, 5, NULL);
xTaskCreate(i2c_test_task, "i2c_test_task_0", 1024 * 2, (void* ) 0, 6, NULL);
xTaskCreate(task, "task", 1024 * 2, (void* ) 0, 8, NULL);
xTaskCreate(tx_task, "uart_tx_task", 1024*2, NULL, 4, NULL);
}
Symbol 'SDSPI_DEFAULT_HOST' could not be resolved
-
- Posts: 3
- Joined: Mon Apr 25, 2022 2:56 pm
Who is online
Users browsing this forum: Majestic-12 [Bot] and 77 guests