 a96f23af9b
			
		
	
	
		a96f23af9b
		
			
		
	
	
	
	
		
			
			* fix multithread logic * more buffer for dallas id string * update apps to use new logic * delay_us small speedup * add consant qualifier to gpio records and some core api * fix some apps to use simpler method of getting gpio record * fix ibutton app, stupid stack problem
		
			
				
	
	
		
			177 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			177 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #pragma once
 | |
| #include "flipper.h"
 | |
| #include "flipper_v2.h"
 | |
| #include "one_wire_timings.h"
 | |
| 
 | |
| class OneWireGpioSlave {
 | |
| private:
 | |
|     const GpioPin* gpio;
 | |
| 
 | |
| public:
 | |
|     OneWireGpioSlave(const GpioPin* one_wire_gpio);
 | |
|     ~OneWireGpioSlave();
 | |
|     void start(void);
 | |
|     void stop(void);
 | |
|     bool emulate(uint8_t* buffer, uint8_t length);
 | |
| 
 | |
|     bool check_reset(void);
 | |
|     bool show_presence(void);
 | |
|     bool receive_and_process_cmd(void);
 | |
|     bool receive(uint8_t* data, const uint8_t data_length);
 | |
|     bool receiveBit(void);
 | |
| 
 | |
|     bool overdrive_mode = false;
 | |
| 
 | |
|     OneWiteTimeType wait_while_gpio(volatile OneWiteTimeType retries, const bool pin_value);
 | |
| };
 | |
| 
 | |
| OneWireGpioSlave::OneWireGpioSlave(const GpioPin* one_wire_gpio) {
 | |
|     gpio = one_wire_gpio;
 | |
| }
 | |
| 
 | |
| OneWireGpioSlave::~OneWireGpioSlave() {
 | |
|     stop();
 | |
| }
 | |
| 
 | |
| void OneWireGpioSlave::start(void) {
 | |
|     gpio_init(gpio, GpioModeOutputOpenDrain);
 | |
| }
 | |
| 
 | |
| void OneWireGpioSlave::stop(void) {
 | |
|     gpio_init(gpio, GpioModeAnalog);
 | |
| }
 | |
| 
 | |
| bool OneWireGpioSlave::emulate(uint8_t* buffer, uint8_t length) {
 | |
|     if(!check_reset()) {
 | |
|         printf("reset error\n");
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     if(!show_presence()) {
 | |
|         printf("presence error\n");
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     if(!receive_and_process_cmd()) {
 | |
|         printf("receive_and_process_cmd error\n");
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     printf("ok\n");
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| OneWiteTimeType OneWireGpioSlave::wait_while_gpio(OneWiteTimeType time, const bool pin_value) {
 | |
|     uint32_t start = DWT->CYCCNT;
 | |
|     uint32_t time_ticks = time * (SystemCoreClock / 1000000.0f);
 | |
| 
 | |
|     while(((DWT->CYCCNT - start) < time_ticks)) {
 | |
|         if(gpio_read(gpio) != pin_value) {
 | |
|             uint32_t time = (DWT->CYCCNT - start);
 | |
|             time /= (SystemCoreClock / 1000000.0f);
 | |
|             return time;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| bool OneWireGpioSlave::check_reset(void) {
 | |
|     while(gpio_read(gpio) == true) {
 | |
|     }
 | |
| 
 | |
|     /*if(wait_while_gpio(OneWireEmulateTiming::RESET_TIMEOUT * 20, true) == 0) {
 | |
|         printf("RESET_TIMEOUT\n");
 | |
|         return false;
 | |
|     }*/
 | |
| 
 | |
|     const OneWiteTimeType time_remaining =
 | |
|         wait_while_gpio(OneWireEmulateTiming::RESET_MAX[0], false);
 | |
| 
 | |
|     if(time_remaining == 0) {
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     if(overdrive_mode && ((OneWireEmulateTiming::RESET_MAX[0] -
 | |
|                            OneWireEmulateTiming::RESET_MIN[0]) <= time_remaining)) {
 | |
|         // normal reset detected
 | |
|         overdrive_mode = false;
 | |
|     };
 | |
| 
 | |
|     bool result = (time_remaining <= OneWireEmulateTiming::RESET_MAX[0]) &&
 | |
|                   time_remaining >= OneWireEmulateTiming::RESET_MIN[overdrive_mode];
 | |
| 
 | |
|     return result;
 | |
| }
 | |
| 
 | |
| bool OneWireGpioSlave::show_presence(void) {
 | |
|     wait_while_gpio(OneWireEmulateTiming::PRESENCE_TIMEOUT, true);
 | |
|     gpio_write(gpio, false);
 | |
|     delay_us(OneWireEmulateTiming::PRESENCE_MIN[overdrive_mode]);
 | |
|     gpio_write(gpio, true);
 | |
|     /*OneWiteTimeType wait_time = OneWireEmulateTiming::PRESENCE_MAX[overdrive_mode] -
 | |
|                                 OneWireEmulateTiming::PRESENCE_MIN[overdrive_mode];
 | |
|     if(wait_while_gpio(wait_time, false) == 0) {
 | |
|         return false;
 | |
|     }*/
 | |
| 
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| bool OneWireGpioSlave::receive_and_process_cmd(void) {
 | |
|     uint8_t cmd;
 | |
|     receive(&cmd, 1);
 | |
|     printf("cmd %x\n", cmd);
 | |
|     return false;
 | |
| }
 | |
| 
 | |
| bool OneWireGpioSlave::receiveBit(void) {
 | |
|     // wait while bus is HIGH
 | |
|     OneWiteTimeType time = OneWireEmulateTiming::SLOT_MAX[overdrive_mode];
 | |
|     time = wait_while_gpio(time, true);
 | |
|     if(time == 0) {
 | |
|         printf("RESET_IN_PROGRESS\n");
 | |
|         return false;
 | |
|     }
 | |
|     /*while ((DIRECT_READ(pin_baseReg, pin_bitMask) == 0) && (--retries != 0));
 | |
|     if (retries == 0)
 | |
|     {
 | |
|         _error = Error::RESET_IN_PROGRESS;
 | |
|         return false;
 | |
|     }*/
 | |
| 
 | |
|     // wait while bus is LOW
 | |
|     time = OneWireEmulateTiming::MSG_HIGH_TIMEOUT;
 | |
|     time = wait_while_gpio(time, false);
 | |
|     if(time == 0) {
 | |
|         printf("TIMEOUT_HIGH\n");
 | |
|         return false;
 | |
|     }
 | |
|     /*while ((DIRECT_READ(pin_baseReg, pin_bitMask) != 0) && (--retries != 0));
 | |
|     if (retries == 0)
 | |
|     {
 | |
|         _error = Error::AWAIT_TIMESLOT_TIMEOUT_HIGH;
 | |
|         return false;
 | |
|     }*/
 | |
| 
 | |
|     // wait a specific time to do a read (data is valid by then), // first difference to inner-loop of write()
 | |
|     time = OneWireEmulateTiming::READ_MIN[overdrive_mode];
 | |
|     time = wait_while_gpio(time, true);
 | |
|     //while ((DIRECT_READ(pin_baseReg, pin_bitMask) == 0) && (--retries != 0));
 | |
| 
 | |
|     return (time > 0);
 | |
| }
 | |
| 
 | |
| bool OneWireGpioSlave::receive(uint8_t* data, const uint8_t data_length) {
 | |
|     uint8_t bytes_received = 0;
 | |
|     for(; bytes_received < data_length; ++bytes_received) {
 | |
|         uint8_t value = 0;
 | |
| 
 | |
|         for(uint8_t bitMask = 0x01; bitMask != 0; bitMask <<= 1) {
 | |
|             if(receiveBit()) value |= bitMask;
 | |
|         }
 | |
| 
 | |
|         data[bytes_received] = value;
 | |
|     }
 | |
|     return (bytes_received != data_length);
 | |
| } |