Skip to content

Instantly share code, notes, and snippets.

@Staars
Created October 18, 2022 14:36
Show Gist options
  • Save Staars/2e48ac09e8a5d5235006daa533f6405d to your computer and use it in GitHub Desktop.
Save Staars/2e48ac09e8a5d5235006daa533f6405d to your computer and use it in GitHub Desktop.
Non-usable RISCV ULP driver, because ULP and main cores can not share one I2C bus
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
/* 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 <stdint.h>
#include "ulp_riscv/ulp_riscv.h"
#include "ulp_riscv/ulp_riscv_utils.h"
#include "ulp_riscv/ulp_riscv_adc_ulp_core.h"
#include "ulp_riscv/ulp_riscv_gpio.h"
#include "hal/adc_types.h"
#define BUTTONS_ADC_CHANNEL ADC_CHANNEL_0
#define BUTTONS_ADC_ATTEN ADC_ATTEN_DB_11
#define BUTTONS_ADC_WIDTH ADC_WIDTH_BIT_12
#define Button_MENU 2950 //2920
#define Button_PLAY 2400 //2377
#define Button_UP 950 //938
#define Button_DOWN 450 //411
#define QMA_SDA 4
#define QMA_SCL 5
#define SCL_L ulp_riscv_gpio_output_enable(QMA_SCL)
#define SCL_H ulp_riscv_gpio_output_disable(QMA_SCL)
#define X_SCL ulp_riscv_gpio_get_level(QMA_SCL)
#define SDA_L ulp_riscv_gpio_output_enable(QMA_SDA)
#define SDA_H ulp_riscv_gpio_output_disable(QMA_SDA)
#define X_SDA ulp_riscv_gpio_get_level(QMA_SDA)
#define CLK 20 //ca. 20kHz Takt (measured)
#define T25 ulp_riscv_delay_cycles(CLK / 4)
uint32_t debug_counter = 0;
bool did_init_I2C = false;
uint8_t i2c_dev_addr = 0x12;
int32_t s3eye_button;
int32_t s3eye_button_old;
int32_t button_updated;
int32_t current_adc_value;
int32_t x_accel;
int32_t y_accel;
int32_t z_accel;
int read_button_array(void){
current_adc_value = ulp_riscv_adc_read_channel(ADC_NUM_1, BUTTONS_ADC_CHANNEL);
if(current_adc_value < Button_DOWN){
return 1;
}
if(current_adc_value < Button_UP){
return 2;
}
if(current_adc_value < Button_PLAY){
return 3;
}
if(current_adc_value < Button_MENU){
return 4;
}
return 0;
}
static void init_gpio() {
ulp_riscv_gpio_init(QMA_SDA);
ulp_riscv_gpio_input_enable(QMA_SDA);
ulp_riscv_gpio_set_output_mode(QMA_SDA, RTCIO_MODE_OUTPUT_OD);
ulp_riscv_gpio_pullup_disable(QMA_SDA);
ulp_riscv_gpio_pulldown_disable(QMA_SDA);
ulp_riscv_gpio_output_level(QMA_SDA, 0);
ulp_riscv_gpio_init(QMA_SCL);
ulp_riscv_gpio_input_enable(QMA_SCL);
ulp_riscv_gpio_set_output_mode(QMA_SCL, RTCIO_MODE_OUTPUT_OD);
ulp_riscv_gpio_pullup_disable(QMA_SCL);
ulp_riscv_gpio_pulldown_disable(QMA_SCL);
ulp_riscv_gpio_output_level(QMA_SCL, 0);
}
static void tx_start_bit() {
SDA_H; T25; SCL_H; T25; SDA_L; T25; // -> SDA_L
}
static void tx_stop_bit() { //SCL_H
T25; SCL_L; SDA_L; T25; SCL_H; T25; SDA_H;
}
static void tx_1_bit() { //SCL H
T25; SCL_L; T25; SDA_H; T25; SCL_H; T25;
}
static void tx_0_bit() { //SCL H
T25; SCL_L; T25; SDA_L; T25; SCL_H; T25; // -> SDA_L
}
static uint8_t rx_bit() {
uint8_t x;
T25; SCL_L; SDA_H; T25; x = X_SDA; SCL_H; T25;
return x;
}
static void tx_ack_bit() {
T25; SCL_L; T25; SDA_L; T25; SCL_H; T25; // ->SDA_L
}
static void tx_nack_bit() {
T25; SCL_L; T25; SDA_H; T25; SCL_H; T25;
}
static void tx_byte (uint8_t x) {
for (int i = 0; i < 8; i++) {
if ((x & 0x80) == 0) tx_0_bit();
else tx_1_bit();
x = x << 1;
}
}
void user_delay_us(uint32_t period, void *intf_ptr) {
ulp_riscv_delay_cycles(period * ULP_RISCV_CYCLES_PER_US);
}
int8_t QMA_i2c_write(uint8_t reg_addr, uint8_t *reg_data, uint32_t len) {
uint8_t dev_addr = i2c_dev_addr;
tx_start_bit();
tx_byte((dev_addr << 1) & 0xFE);
uint8_t x = rx_bit();
tx_byte(reg_addr);
x |= rx_bit();
for (int i = 0; i < len; i++) {
tx_byte(reg_data[i]);
x |= rx_bit();
}
tx_stop_bit();
return x;
}
int8_t QMA_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t len) {
uint8_t dev_addr = i2c_dev_addr;
//send source-addr to slave, without data
uint8_t x = QMA_i2c_write(reg_addr, NULL, 0);
//sens slave-adr senden for preface reading process
tx_start_bit();
tx_byte((dev_addr << 1) | 0x01);
x |= rx_bit();
//read data sequentially
uint8_t y;
for (int j = 0; j < len; j++) {
for (int i = 0; i < 8; i++) {
y <<= 1;
y |= rx_bit();
}
reg_data[j] = y;
if (j < (len-1)) tx_ack_bit();
}
tx_nack_bit(); //last read byte -> acknowledge with NACK
tx_stop_bit();
return x;
}
void set_bit(uint8_t *byte, uint8_t n, bool value)
{
*byte = (*byte & ~(1UL << n)) | (value << n);
}
void QMA_set_mode(uint8_t mode){
uint8_t data;
QMA_i2c_read(0x11,&data,1);
set_bit(&data, 7, mode);
QMA_i2c_write(0x11,&data,1);
}
void QMA_read_accel(){
uint8_t buffer[6];
QMA_i2c_read(0x1,buffer,6);
x_accel = buffer[1] << 8;
x_accel |= buffer[0] >> 1;
y_accel = buffer[3] << 8;
y_accel |= buffer[2] >> 1;
z_accel = buffer[5] << 8;
z_accel |= buffer[4] >> 1;
}
int main (void)
{
init_gpio();
if(did_init_I2C){
QMA_read_accel();
}
else{
uint8_t data = 0xb6;
QMA_i2c_write(0x36,&data,1);
data = 0;
QMA_i2c_write(0x36,&data,1);
QMA_set_mode(1); //MODE_ACTIVE
did_init_I2C = true;
}
s3eye_button = read_button_array();
if(s3eye_button != s3eye_button_old){
s3eye_button_old = s3eye_button;
button_updated = 1;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment