some boilerplate and notes about i2c slave
This commit is contained in:
parent
33a42edc7f
commit
6be6cee2ac
|
@ -8,6 +8,22 @@ main mcu firmware for the GAT Nametag originally shown at Supercon 8.
|
|||
This is a MounRiver Studio project. Build in MRS.
|
||||
|
||||
|
||||
## loading firmware over USB
|
||||
|
||||
Easiest way is to use WCHISPStudio. This comes bundled with MRS. `Tools > WCH In-System Programmer`
|
||||
|
||||
|
||||
## enabling debug
|
||||
|
||||
By default, the debug interface is locked. To unlock the debug interface, do the following within a roughly 5 second window:
|
||||
|
||||
- Hold down BOOT, then plug in to USB
|
||||
- Device should be dected in WCHISPStudio
|
||||
- Within WCHISPStudio, click the `Enable Simulat` button at the bottom
|
||||
|
||||
At this point flash will be cleared and the debug interface will be re-enabled.
|
||||
|
||||
|
||||
## bugs, quirks, omissions
|
||||
|
||||
- this micro has VERY SLOW flash. therefore, most user code is executed from RAM. additionally, the flash is protected and not really documented. will take time to reverse engineer it from the provided .a file to possibly determine if wait states can be adjusted.
|
||||
|
@ -15,6 +31,8 @@ This is a MounRiver Studio project. Build in MRS.
|
|||
- i2c master is bitbanged and may still have bugs.
|
||||
|
||||
- i2c slave is bitbanged and hasn't been tested at all.
|
||||
|
||||
- i2c master and i2c slave are both BLOCKING. this means that while data is being manipulated on OLED or other I2C slaves on the addon, the addon will not respond as I2C slave. to address this device as a slave, ack poll until you get an ack, then send your payload. make sure to wait at least 4 bit times before trying each ack poll.
|
||||
|
||||
- "idle mode" isn't really a power saving mode. no time to implement. need to do the following to implement this properly:
|
||||
- implement a low power mode in the sub MCU as well, tell it to go to sleep
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
|
||||
|
||||
|
||||
#define I2CSS_ERR_TIMEOUT 6 // timeout in bit-times before i2c slave releases control
|
||||
#define I2CSS_IDLE_TIMEOUT 3 // idle timeout required in bit-times before i2c slave can be addressed again
|
||||
#define I2CSS_ERR_TIMEOUT 3 // timeout in bit-times before i2c slave releases control
|
||||
#define I2CSS_IDLE_TIMEOUT 4 // idle timeout required in bit-times before i2c slave can be addressed again
|
||||
|
||||
|
||||
// todo: use with struct instead of hard-coding to allow for multiple slaves, but make it fast too
|
||||
|
@ -54,7 +54,7 @@ static uint16_t idle_timeout = 0;
|
|||
|
||||
|
||||
|
||||
static int8_t i2css_wait_for_scl_hi()
|
||||
static inline int8_t i2css_wait_for_scl_hi()
|
||||
{
|
||||
int16_t timeout = I2CSS_ERR_TIMEOUT * bit_time;
|
||||
|
||||
|
@ -62,7 +62,7 @@ static int8_t i2css_wait_for_scl_hi()
|
|||
return I2CSS_OK;
|
||||
}
|
||||
|
||||
static int8_t i2css_wait_for_scl_lo()
|
||||
static inline int8_t i2css_wait_for_scl_lo()
|
||||
{
|
||||
uint8_t old_data = SDA_GET();
|
||||
int16_t timeout = I2CSS_ERR_TIMEOUT * bit_time;
|
||||
|
@ -103,6 +103,7 @@ int8_t i2css_idle_init(struct I2CSoftSlave *slave)
|
|||
|
||||
// returns 0 if idle, or -1 if not idle.
|
||||
// if not idle, restarts the idle timer.
|
||||
__HIGH_CODE
|
||||
int8_t i2css_idle_check(struct I2CSoftSlave *slave)
|
||||
{
|
||||
// requires a hardware timer or something to manage bus idle time
|
||||
|
@ -117,6 +118,7 @@ int8_t i2css_idle_check(struct I2CSoftSlave *slave)
|
|||
return -1;
|
||||
}
|
||||
|
||||
__HIGH_CODE
|
||||
int8_t i2css_read(struct I2CSoftSlave *slave)
|
||||
{
|
||||
int8_t i;
|
||||
|
@ -164,6 +166,7 @@ int8_t i2css_read(struct I2CSoftSlave *slave)
|
|||
return ack ? I2CSS_NACK : I2CSS_OK;
|
||||
}
|
||||
|
||||
__HIGH_CODE
|
||||
int8_t i2css_write(struct I2CSoftSlave *slave)
|
||||
{
|
||||
int8_t i;
|
||||
|
@ -219,6 +222,7 @@ int8_t i2css_write(struct I2CSoftSlave *slave)
|
|||
// blocking implementation of i2c slave, with 8-bit address register.
|
||||
// basically, simulates a 24C02 EEPROM.
|
||||
// externally kicked off by a low transition on SCL.
|
||||
__HIGH_CODE
|
||||
static inline int8_t i2css_process(struct I2CSoftSlave *slave)
|
||||
{
|
||||
int32_t i;
|
||||
|
@ -281,6 +285,7 @@ static inline int8_t i2css_process(struct I2CSoftSlave *slave)
|
|||
return ret;
|
||||
}
|
||||
|
||||
__HIGH_CODE
|
||||
int8_t i2css_blocking(struct I2CSoftSlave *slave)
|
||||
{
|
||||
int8_t ret;
|
||||
|
@ -300,6 +305,7 @@ int8_t i2css_blocking(struct I2CSoftSlave *slave)
|
|||
}
|
||||
|
||||
// call this function with SDA falling low interrupt.
|
||||
__HIGH_CODE
|
||||
int8_t i2css_start(struct I2CSoftSlave *slave)
|
||||
{
|
||||
uint8_t scl;
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* i2c_slave_handler.c
|
||||
*
|
||||
* Created on: Oct 30, 2024
|
||||
* Author: true
|
||||
*/
|
||||
|
||||
#include "soft_i2c_slave_handler.h"
|
||||
#include "soft_i2c_slave.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
|
||||
struct I2CSoftSlave addon_i2c;
|
||||
|
||||
|
||||
|
||||
void i2css_addon_init()
|
||||
{
|
||||
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* soft_i2c_slave_handler.h
|
||||
*
|
||||
* Created on: Oct 30, 2024
|
||||
* Author: true
|
||||
*/
|
||||
|
||||
#ifndef USER_COMM_SOFT_I2C_SLAVE_HANDLER_H_
|
||||
#define USER_COMM_SOFT_I2C_SLAVE_HANDLER_H_
|
||||
|
||||
|
||||
|
||||
extern struct I2CSoftSlave addon_i2c;
|
||||
|
||||
|
||||
|
||||
#endif /* USER_COMM_SOFT_I2C_SLAVE_HANDLER_H_ */
|
|
@ -133,7 +133,7 @@ void rtcisr_init()
|
|||
|
||||
rtc_reset_trig();
|
||||
|
||||
PFIC_SetPriority(RTC_IRQn, 0x00); // rtc is highest priority interrupt
|
||||
PFIC_SetPriority(RTC_IRQn, 0x10); // rtc is second highest priority interrupt
|
||||
PFIC_EnableIRQ(RTC_IRQn);
|
||||
}
|
||||
|
||||
|
@ -427,6 +427,10 @@ __INTERRUPT
|
|||
__HIGH_CODE
|
||||
void RTC_IRQHandler(void)
|
||||
{
|
||||
// todo:
|
||||
// - get real elapsed time
|
||||
// - calculate interrupts/second actually executed
|
||||
|
||||
// clear interrupt flag and reset RTC
|
||||
rtc_reset_trig();
|
||||
|
||||
|
|
|
@ -14,8 +14,12 @@
|
|||
#include "CH59x_common.h"
|
||||
#include "port_intr.h"
|
||||
|
||||
#include "comm/soft_i2c_slave.h"
|
||||
#include "comm/soft_i2c_slave_handler.h"
|
||||
|
||||
#include "hw/ch32sub.h"
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
|
@ -46,8 +50,11 @@ void port_intr_init()
|
|||
// clear state
|
||||
R16_PB_INT_IF = 0xff;
|
||||
|
||||
// then enable interrupt as low priority
|
||||
PFIC_SetPriority(RTC_IRQn, 0x30);
|
||||
PFIC_SetPriority(GPIO_A_IRQn, 0x00); // high priority
|
||||
PFIC_EnableIRQ(GPIO_A_IRQn);
|
||||
|
||||
// then enable interrupt
|
||||
PFIC_SetPriority(GPIO_B_IRQn, 0x30); // low priority
|
||||
PFIC_EnableIRQ(GPIO_B_IRQn);
|
||||
}
|
||||
|
||||
|
@ -62,6 +69,13 @@ void GPIOA_IRQHandler(void)
|
|||
|
||||
// clear flags
|
||||
R16_PA_INT_IF = flag;
|
||||
|
||||
// addon header i2c data pin
|
||||
if (flag & (1 << 13)) {
|
||||
SetSysClock(SYSCLK_FREQ_USEI2C);
|
||||
i2css_start(&addon_i2c);
|
||||
SetSysClock(SYSCLK_FREQ_IDLE);
|
||||
}
|
||||
}
|
||||
|
||||
__INTERRUPT
|
||||
|
|
Loading…
Reference in New Issue