void check_pressure_status(void){ //TANK LEER REQUEST if (tanklevel <= TANK_MIN && rm_status.SchwimmSchalter == false) { //rm_status.SchwimmSchalter = true; if(requested_ID != 0){ send_OUT_OF_WATER(geraete_IPs[requested_ID - 1]); requested_ID = 0; } send_request(); PIN_SET(ZENTRALVENTIL, OFF); //VENTIL_ZU (aus sicherheit) } if (tanklevel >= TANK_MAX && rm_status.SchwimmSchalter == true) { rm_status.SchwimmSchalter = false; abort_request(); } //STANDARD RM ECO if (!PIN_HIGH(DRUCKSCHALTER) && !pumpe_status) { PIN_SET(PUMPE, ON); pumpe_status = true; } if (PIN_HIGH(DRUCKSCHALTER) && pumpe_status) { PIN_SET(PUMPE, OFF); pumpe_status = false; } }
int sceKermit_driver_9160841C(int pin_n, int allow_callbacks) { /* lock the power source, no shutdown */ int res = sceKernelPowerLock(0); /* check if valid */ if (res == 0) { /* wait? */ sub_00000908(); /* suspend interrupts */ int intr = sceKernelCpuSuspendIntr(); PIN_HIGH(0xBC300038, pin_n); PIN_LOW(0xBC300050, pin_n); PIN_HIGH(0xBC300050, pin_n); /* resume all the interrupts */ sceKernelCpuResumeIntr(intr); /* wait on work sema */ if (allow_callbacks) sceKernelWaitSemaCB(g_work_sema[pin_n], 1, NULL); else sceKernelWaitSema(g_work_sema[pin_n], 1, NULL); /* unlock power */ res = sceKernelPowerUnlock(0); /* resolve +ve res to 0 */ if (res > 0) res = 0; } /* return the result */ return res; }
static void Initialize_SPI(void) { // Initialize SPI Interface pins as GPIOs LCD3310_MOSI_DIR |= LCD3310_MOSI_MASK; LCD3310_SCK_DIR |= LCD3310_SCK_MASK; PIN_HIGH(LCD3310_SCK_OUT); PIN_HIGH(LCD3310_MOSI_OUT); }
void ps2_send_byte(uint8_t byte) { uint8_t sreg = SREG; cli(); uint8_t i = 11; DDR_CONFIG_OUT(PS2_DATA); DDR_CONFIG_OUT(PS2_CLOCK); /* > 100 us clock low */ PIN_CLEAR(PS2_CLOCK); while (i--) _delay_us(10); /* data low */ PIN_CLEAR(PS2_DATA); /* clock high */ PIN_SET(PS2_CLOCK); /* Wait until clock is low again */ DDR_CONFIG_IN(PS2_CLOCK); while (PIN_HIGH(PS2_CLOCK)); uint8_t parity = 1; bitcount = 0; while(bitcount < 9) { /* Parity */ if (bitcount == 8) { PIN_CLEAR(PS2_DATA); if (parity) PIN_SET(PS2_DATA); } /* data */ else { PIN_CLEAR(PS2_DATA); if (byte & 0x01) { PIN_SET(PS2_DATA); parity ^= 1; } byte >>= 1; } /* The keyboard generates the clock */ while (!PIN_HIGH(PS2_CLOCK)); while (PIN_HIGH(PS2_CLOCK)); bitcount++; } DDR_CONFIG_IN(PS2_DATA); PIN_CLEAR(PS2_DATA); PIN_CLEAR(PS2_CLOCK); /* Wait for the ack from the keyboard */ while (PIN_HIGH(PS2_DATA)); while (PIN_HIGH(PS2_CLOCK)); SREG = sreg; }
uint8_t spi_send(uint8_t outdata) { DDR_CONFIG_IN(SOFT_SPI_MISO); uint8_t j, indata = indata; for(j = 0; j < 8; j++) { if(outdata & 0x80) PIN_SET(SOFT_SPI_MOSI); else PIN_CLEAR(SOFT_SPI_MOSI); PIN_SET(SOFT_SPI_SCK); indata <<= 1; if(PIN_HIGH(SOFT_SPI_MISO)) indata |= 1; PIN_CLEAR(SOFT_SPI_SCK); outdata <<= 1; } DDR_CONFIG_OUT(SOFT_SPI_MISO); return indata; }
bool buttons_getButtonState(buttons_button_t button) { switch( button ){ case BUTTON_0: return !PIN_HIGH(BUTTON_0); break; case BUTTON_1: return !PIN_HIGH(BUTTON_1); break; case BUTTON_2: return !PIN_HIGH(BUTTON_2); break; } return false; }
// send a serial 1 on +strand+ void xmas_one(int strand_pin) { PIN_LOW(strand_pin); _delay_us(20); PIN_HIGH(strand_pin); _delay_us(8); PIN_LOW(strand_pin); }
static bool door_locking(void) { if( PIN_HIGH(DOOR_LOCK) ){ return false; } return true; }
/* * lome6 periodical countdown timer function * counts down time in ~seconds since power button long is pressed (needed to prevent watchdog action) * manages power on delay */ void lome6_timersec(void) { if (iCountdownTimer > 0) { iCountdownTimer--; if (iCountdownTimer <= 0) PIN_CLEAR(RELAIS_POWER); } // test power on delay counter // if server already on, dont do anything if (iPOD > 0 && PIN_HIGH(POWER_STATE)) { iPOD--; if (iPOD <= 0) { PIN_SET(RELAIS_POWER); _delay_ms(CONF_TIME2PRESS_POWER); PIN_CLEAR(RELAIS_POWER); } } }
// send a serial 0 on +strand+ void xmas_zero(int strand_pin) { PIN_LOW(strand_pin); _delay_us(10); PIN_HIGH(strand_pin); _delay_us(20); PIN_LOW(strand_pin); }
static bool door_barSensor(void) { if( PIN_HIGH(DOOR_LOCK_CONTACT) ){ return true; } return false; }
static inline bool isPressed(void) { if( !PIN_HIGH(BUTTON_BELL) ){ return true; } return false; }
uint8_t noinline hd44780_clock_rw(uint8_t read, uint8_t en) { uint8_t data = 0; /* set EN high, wait for more than 450 ns */ #ifdef HD44780_MULTIEN_SUPPORT if (en == 1) PIN_SET(HD44780_EN1); else if (en == 2) PIN_SET(HD44780_EN2); #else PIN_SET(HD44780_EN1); #endif /* make sure that we really wait for more than 450 ns... */ _delay_us(1); /* read data, if requested. data pins must be configured as input! */ if (read) { if (PIN_HIGH(HD44780_D4)) data |= _BV(0); if (PIN_HIGH(HD44780_D5)) data |= _BV(1); if (PIN_HIGH(HD44780_D6)) data |= _BV(2); if (PIN_HIGH(HD44780_D7)) data |= _BV(3); } /* set EN low */ #ifdef HD44780_MULTIEN_SUPPORT if (en == 1) PIN_CLEAR(HD44780_EN1); else if (en == 2) PIN_CLEAR(HD44780_EN2); #else PIN_CLEAR(HD44780_EN1); #endif return data; }
void rainmaster_check_inputs(void) { //if(!PIN_HIGH(RM_POSITION1)) if(!PIN_HIGH(RM_PUMPKONTAKT)) rm_status.PumpenKontakt = true; else rm_status.PumpenKontakt = false; // Anschluss AL_SSKLARMIN // if(!PIN_HIGH(RM_SCHWIMMER)) rm_status.SchwimmSchalter = true; else rm_status.SchwimmSchalter = false; // Schwimmer AL_SSKLARMAX // if(!PIN_HIGH(RM_POSITION1)) rm_status.Pos1Schalter = true; else rm_status.Pos1Schalter = false; if(rm_status.PumpenFlag == true) rm_offcounter++; else rm_offcounter = 0; my_tanklevel = rainmaster_get_tanklevel(); }
uint8_t noinline clock_rw(uint8_t read) { /* set EN high, wait for more than 450 ns */ PIN_SET(HD44780_EN); /* make sure that we really wait for more than 450 ns... */ _delay_us(0.6); /* read data, if requested. data pins must be configured as input! */ uint8_t data = 0; if (read) { if (PIN_HIGH(HD44780_D4)) data |= _BV(0); if (PIN_HIGH(HD44780_D5)) data |= _BV(1); if (PIN_HIGH(HD44780_D6)) data |= _BV(2); if (PIN_HIGH(HD44780_D7)) data |= _BV(3); } /* set EN low */ PIN_CLEAR(HD44780_EN); return data; }
static void door_update_inputs(void) { door_doorstate &= ~(DOOR_DOOR_CLOSED | DOOR_LOCK_LOCKED | DOOR_HANDLE_PRESSED | DOOR_LOCK_UNLOCKED | DOOR_LOCK_MANUAL_UNLOCKED); //TODO: also query the reed contact here if( !PIN_HIGH(DOOR_DOOR_OPEN_CONTACT) ) door_doorstate |= DOOR_DOOR_CLOSED; if( !PIN_HIGH(DOOR_HANDLE_CONTACT) ) door_doorstate |= DOOR_HANDLE_PRESSED; if( !PIN_HIGH(DOOR_LOCK_LOCKED_CONTACT) ) door_doorstate |= DOOR_LOCK_LOCKED; // TODO: These might be insufficient criteria! if( !PIN_HIGH(DOOR_LOCK_UNLOCKED_CONTACT) ){ // The bar is retracted if( !PIN_HIGH(DOOR_LOCK_CONTACT) ){ // The bar is retracted because we unlocked it door_doorstate |= DOOR_LOCK_UNLOCKED; }else{ door_doorstate |= DOOR_LOCK_MANUAL_UNLOCKED; } } }
static void door_update_inputs(void) { door_doorstate &= ~(DOOR_DOOR_CLOSED | DOOR_LOCK_LOCKED | DOOR_HANDLE_PRESSED | DOOR_LOCK_UNLOCKED| DOOR_LOCK_MANUAL_UNLOCKED); if( !PIN_HIGH(DOOR_DOOR_OPEN_CONTACT) && !PIN_HIGH(DOOR_REED_CONTACT) ) door_doorstate |= DOOR_DOOR_CLOSED; if( !PIN_HIGH(DOOR_HANDLE_CONTACT) ) door_doorstate |= DOOR_HANDLE_PRESSED; if( !PIN_HIGH(DOOR_LOCK_LOCKED_CONTACT) ) door_doorstate |= DOOR_LOCK_LOCKED; // TODO: These are insufficient criteria! if( !PIN_HIGH(DOOR_LOCK_UNLOCKED_CONTACT) ){ // The bar is retracted if( door_locking() ){ door_doorstate |= DOOR_LOCK_MANUAL_UNLOCKED; }else{ // The bar is retracted because we unlocked it door_doorstate |= DOOR_LOCK_UNLOCKED; } } }
/* * lome6 startup function * get the sensor id's from the config and convert them to struct ow_rom_code_t and read the scratchpads * start a first one wire temperature convert */ void lome6_startup(void) { iLCDPage = 0; iTemperatureCPU = 0; iTemperatureSB = 0; iCountdownTimer = 0; iUptime = 0; iPOD = 0; #ifdef LOME6_ONEWIRE_SUPPORT iTemperatureAIR = 0; iTemperaturePSU = 0; iTemperatureRAM = 0; #endif #ifdef LOME6_LCD_SUPPORT WINDOW *ttyWindow = NULL; #endif #ifdef LOME6_ONEWIRE_SUPPORT if (parse_ow_rom(CONF_SENSOR_PSU, &romcodePSU) == -1) { LOME6DEBUG("cannot parse ow rom code for psu sensor\n"); } if (parse_ow_rom(CONF_SENSOR_AIR, &romcodeAIR) == -1) { LOME6DEBUG("cannot parse ow rom code for air sensor\n"); } if (parse_ow_rom(CONF_SENSOR_RAM, &romcodeRAM) == -1) { LOME6DEBUG("cannot parse ow rom code for ram sensor\n"); } ow_temp_start_convert_nowait(NULL); #endif #ifdef LOME6_LCD_SUPPORT ttyWindow = subwin(NULL, CONF_LOME6_LCD_HEIGHT, CONF_LOME6_LCD_WIDTH, 0, 0); #endif // only set iPOD if server not running // (disable power on delay if server is running already) if (PIN_HIGH(POWER_STATE)) iPOD = CONF_LOME6_POD; }
/* * lome6 periodical timer function for display and one wire convert command * * if onewire is supported start onewire temperature convert * if lcd is supported display various information */ void lome6_timer(void) { #ifdef LOME6_ONEWIRE_SUPPORT // read 1w temperatures iTemperaturePSU = lome6_get_temperature(&romcodePSU); iTemperatureAIR = lome6_get_temperature(&romcodeAIR); iTemperatureRAM = lome6_get_temperature(&romcodeRAM); #endif // LOME6_ONEWIRE_SUPPORT #ifdef LOME6_LCD_SUPPORT wclear(ttyWindow); if (iLCDPage == 0) { // display uptime and date+time uint32_t working_hours = (clock_get_time() - clock_get_startup()) / 60; struct clock_datetime_t datetime; clock_current_localtime(&datetime); wprintw_P(ttyWindow, PSTR("%02d:%02d %02d.%02d.%04d"), datetime.hour, datetime.min, datetime.day, datetime.month, (datetime.year + 1900)); wclrtoeol(ttyWindow); wmove(ttyWindow, 1, 0); wprintw_P(ttyWindow, PSTR("Uptime: %02lu:%02d"), working_hours / 60, working_hours % 60); wclrtoeol(ttyWindow); #ifndef LOME6_ONEWIRE_SUPPORT if (!PIN_HIGH(POWER_STATE)) iLCDPage = 4; else iLCDPage = 0; #else iLCDPage++; #endif #ifdef LOME6_ONEWIRE_SUPPORT } else if (iLCDPage == 1) { // display onewire temperature sensor data wprintw_P(ttyWindow, PSTR("Temperature")); wclrtoeol(ttyWindow); wmove(ttyWindow, 1, 0); wprintw_P(ttyWindow, PSTR("AIR: %02d.%d"), iTemperatureAIR / 10, iTemperatureAIR % 10); wclrtoeol(ttyWindow); iLCDPage++; } else if (iLCDPage == 2) { // display onewire temperature sensor data wprintw_P(ttyWindow, PSTR("Temperature:")); wclrtoeol(ttyWindow); wmove(ttyWindow, 1, 0); wprintw_P(ttyWindow, PSTR("RAM: %02d.%d"), iTemperatureRAM / 10, iTemperatureRAM % 10); wclrtoeol(ttyWindow); iLCDPage++; } else if (iLCDPage == 3) { // display onewire temperature sensor data wprintw_P(ttyWindow, PSTR("Temperature")); wclrtoeol(ttyWindow); wmove(ttyWindow, 1, 0); wprintw_P(ttyWindow, PSTR("PSU: %02d.%d"), iTemperaturePSU / 10, iTemperaturePSU % 10); wclrtoeol(ttyWindow); iLCDPage++; #endif //LOME6_ONEWIRE_SUPPORT } else if (iLCDPage == 4) { // display temperature data wprintw_P(ttyWindow, PSTR("Temperature")); wclrtoeol(ttyWindow); wmove(ttyWindow, 1, 0); wprintw_P(ttyWindow, PSTR("CPU: %02d.%d"), iTemperatureCPU / 10, iTemperatureCPU % 10); wclrtoeol(ttyWindow); iLCDPage++; } else if (iLCDPage == 5) { // display temperature data wprintw_P(ttyWindow, PSTR("Temperature")); wclrtoeol(ttyWindow); wmove(ttyWindow, 1, 0); wprintw_P(ttyWindow, PSTR("SB: %02d.%d"), iTemperatureSB / 10, iTemperatureSB % 10); wclrtoeol(ttyWindow); iLCDPage = 0; } // start a new convert in next round ow_temp_start_convert_nowait(NULL); #endif // LOME6_LCD_SUPPORT }
/** main function */ int main(void) { // SPCR &= ~(1<<SPE); // TIMSK0 &= ~(1<<TOIE1); wdt_disable(); /* Clear WDRF in MCUSR */ MCUSR &= ~(1<<WDRF); /* Write logical one to WDCE and WDE */ /* Keep old prescaler setting to prevent unintentional time-out */ WDTCSR |= (1<<WDCE) | (1<<WDE); /* Turn off WDT */ WDTCSR = 0x00; //volatile long l; // for(l=0;l<1000000;l++); DDR_CONFIG_IN(CONFIG1); PIN_SET(CONFIG1); wdt_enable(WDTO_2S); wdt_reset(); volatile unsigned long l; for(l=0;l<10;l++); if( !PIN_HIGH(CONFIG1) ){ global.config = 30; }else{ global.config = 21; } leds_init(); wdt_reset(); if( global.config == 21 ){ DDR_CONFIG_IN(JUMPER1C1); PIN_SET(JUMPER1C1); }else if( global.config == 30 ){ DDR_CONFIG_IN(JUMPER1C2); PIN_SET(JUMPER1C2); adc_init(); uint16_t bat = adc_getChannel(6); if( bat < ADC_MINBATIDLE ){ //global.flags.lowbat = 1; } } wdt_reset(); init_pwm(); #if SERIAL_UART uart1_init( UART_BAUD_SELECT(UART_BAUDRATE,F_CPU)); stdout = &mystdout; #endif #if RC5_DECODER rc5_init(); #endif wdt_reset(); #if STATIC_SCRIPTS init_script_threads(); #endif settings_read(); //if((global.config == 21 && !PIN_HIGH(JUMPER1C1)) || (global.config== 30 && !PIN_HIGH(JUMPER1C2))) // interfaces_setEnabled(IFACE_RF,0); control_init(); wdt_reset(); #if RS485_CTRL rs485_init(); zbus_core_init(); #endif //rf_init(); packet_init(idbuf[0],0); wdt_reset(); srandom(random_seed); random_seed = random(); /* enable interrupts globally */ sei(); // global.state = STATE_RUNNING; // global.state = STATE_PAUSE; // global.flags.running = 0; while (1) { wdt_reset(); //leds_main(); #if 1 packet_tick(); #else if(packetbase ){//> 32){ packetbase = 0; packet_tick(); //if(main_reset++ > 16000) // jump_to_bootloader(); //uint16_t bat = adc_getChannel(6); /*if( bat < ADC_MINBATIDLE ){ global.flags.lowbat = 1; }*/ } #endif //if( global.flags.lowbat ){ // control_lowbat(); //} if( global.flags.timebase ){ //control_tick(); global.flags.timebase=0; } /* after the last pwm timeslot, rebuild the timeslot table */ //if (global.flags.last_pulse) { // global.flags.last_pulse = 0; //if(global.flags.running) //update_pwm_timeslots(); //} /* at the beginning of each pwm cycle, call the fading engine and * execute all script threads */ if (global.flags.new_cycle) { global.flags.new_cycle = 0; if(control_faderunning) update_brightness(); if(global.flags.running){ #if STATIC_SCRIPTS // execute_script_threads(); #endif } //continue; } #if RC5_DECODER #endif #if RS485_CTRL rs485_process(); #endif #if SERIAL_UART //serial_process(); #endif } }
static void dht_read(void) { PIN_SET(DHT); _delay_us(30); DDR_CONFIG_IN(DHT); /* Read in timingss, which takes approx. 4,5 milliseconds. * We do not disable interrupts, because a failed read is outweighed * by a non-serviced interrupt. Please never enclose the for-loop * with an ATOMIC_BLOCK! */ uint8_t last_state = PIN_BV(DHT); uint8_t j = 0; uint8_t data[5]; for (uint8_t i = 0; i < MAXTIMINGS; i++) { uint8_t counter = 0; uint8_t current_state; while (last_state == (current_state = PIN_HIGH(DHT))) { _delay_us(5); if (++counter == 20) { DHT_DEBUG("read timeout, edge=%u", i); return; /* timeout in conversation */ } } last_state = current_state; /* ignore first three transitions */ if ((i >= 4) && (i % 2 == 0)) { /* shift each bit into the storage bytes */ data[j / 8] <<= 1; if (counter > 7) /* 7*5=35us */ data[j / 8] |= 1; j++; } } /* check we read 40 bits and that the checksum matches */ if ((j < 40) || (data[4] != ((data[0] + data[1] + data[2] + data[3]) & 0xFF))) { DHT_DEBUG("read failed, bits=%u, %02X %02X %02X %02X %02X", j, data[0], data[1], data[2], data[3], data[4]); return; } int16_t t; #if DHT_TYPE == DHT_TYPE_11 t = data[2]; t *= 10; dht_global.temp = t; t = data[0]; t *= 10; dht_global.humid = t; #elif DHT_TYPE == DHT_TYPE_22 t = data[2] << 8 | data[3]; if (t & 0x8000) { t &= ~0x8000; t = -t; } dht_global.temp = t; t = data[0] << 8 | data[1]; dht_global.humid = t; #endif DHT_DEBUG("t=%d, h=%d%%", dht_global.temp, dht_global.humid); }
int sceKermit_driver_4F75AA05(u8 *data, u32 cmd_mode, u32 cmd, u32 argc, u32 allow_callback, u8 *resp) { /* check if we are not accepting kermit calls */ if (!g_enable_kermit) { /* wait 10ms */ sceKernelDelayThread(10 * 1000); return 0; } /* lock the mutex, no timeout */ sceKernelLockMutex(g_mutex_id, 1, NULL); /* update counter */ g_active_connections++; /* release the mutex */ sceKernelUnlockMutex(g_mutex_id, 1); /* use specific ID on modes KERMIT_MODE_AUDIO and mode 6. This is to improve parallelism and async */ if (cmd_mode == KERMIT_MODE_AUDIO) proc_n = 1; else if (cmd_mode == 6) proc_n = 2; else proc_n = 0; /* construct sema timeout of 5 seconds */ u32 timeout = 5 * 1000 * 1000; /* wait on sema */ int res = sceKernelWaitSema(g_access_sema[proc_n], 1, &timeout); /* check if we error'd */ if (res != 0) { /* go the the clean up code */ goto exit; } /* read the message pipe */ res = sceKernelReceiveMsgPipe(g_pipe_id, &sema_id, sizeof(SceUID), 0, 0, 0); /* check if error occured */ if (res != 0) { /* error, clean up and exit */ goto exit; } /* now set the command number */ g_command[proc_n].cmd_type = (cmd_mode << 16) | cmd; /* DMA align the arg count. Max = 16 args */ u32 packet_size = ((argc + sizeof(u64) + 1) & 0xFFFFFFF8) * sizeof(u64); /* store packet info */ packet.cmd = cmd; packet.sema_id = sema_id; packet.self = packet; /* send data to kermit */ g_command[proc_n].kermit_addr = sub_00000A98(packet, packet_size); /* wait? */ sub_00000908(); /* lock the power, prevent shutdown */ res = sceKernelPowerLock(0); /* check if error occured */ if (res != 0) { /* error, clean up and exit */ goto exit; } /* suspend cpu interrupts */ int intr = sceKernelCpuSuspendIntr(); /* signal low, then high for the process */ PIN_LOW(0xBC300050, proc_n + 4); PIN_HIGH(0xBC300050, proc_n + 4); /* resume the CPU interrupts */ sceKernelCpuResumeIntr(intr); /* check for callback permitting process */ if (allow_callback) sceKernelWaitSemaCB(sema_id, 1, NULL); else sceKernelWaitSema(sema_id, 1, NULL); /* send sema id back into pipe, act as a circular queue */ sceKernelSendMsgPipe(g_pipe_id, &sema_id, sizeof(SceUID), 0, 0, 0); /* now, check if there is a response */ if (resp) { /* copy data from packet to response */ ((u64 *)resp)[0] = ((u64 *)packet)[0]; } /* unlock power */ res = sceKernelPowerUnlock(0); /* exit and cleanup code */ exit: /* lock mutex for exclusive access, no timeout */ sceKernelLockMutex(g_mutex_id, 1, NULL); /* update counter */ g_active_connections--; /* release the mutex */ sceKernelUnlockMutex(g_mutex_id, 1); /* check result */ if (res >= 0) res = 0; /* return result */ return res; }
// begin a serial packet on +strand+ void xmas_begin(int strand_pin) { PIN_HIGH(strand_pin); _delay_us(10); PIN_LOW(strand_pin); }
void kde_kdr1000_interrupt(void) { if (PIN_HIGH(KDE_KDR1000_PRES)) { /* idle = reset all */ kdr1000_bitcount = 5; kdr1000_data = 0; kdr1000_digit = 0; kdr1000_parity = 0x10; kdr1000_lrc = 0; kdr1000_badflag = 0; kdr1000_end = 0; } else { /* badge presence */ if ( ! PIN_HIGH(KDE_KDR1000_STROBE) ) { { /* sample DATA */ if (PIN_HIGH(KDE_KDR1000_DATA)) { /* at the beginning data stays hi for some time, * we have to ignore this */ if ((kdr1000_digit == 0) && (kdr1000_bitcount == 5)) return; } else /* data LO means bit=1 */ { if (kdr1000_bitcount > 1) kdr1000_parity ^= 0x10; kdr1000_data |= 0x10; } kdr1000_bitcount--; /* next bit */ if (kdr1000_bitcount == 0) /* last bit */ { kdr1000_bitcount = 5; /* parity check */ if ( (kdr1000_data & 0x10) == kdr1000_parity ) { kdr1000_data &= 0xF; /* keep data bits */ if (kdr1000_digit < KDR1000_BUFFER_SIZE ) /* prevent out-of-boundary */ kdr1000_buffer[kdr1000_digit] = kdr1000_data; if (kdr1000_data == 0xF) /* end sentinel */ { kdr1000_end = 1; } else if (kdr1000_end == 1) { /* the next byte after end sentinel is the LRC */ #ifdef DEBUG_KDE_KDR1000 KDE_DEBUG ("MSR: end sentinel 0xF then LRC\n"); KDE_DEBUG ("DATA (%d) =", kdr1000_digit+1); for (uint8_t i = 0; i<=kdr1000_digit; i++) printf_P(PSTR(" %x"), kdr1000_buffer[i]); printf_P(PSTR("\n")); KDE_DEBUG ("LCR calcolato = %x, letto = %x", kdr1000_lrc, kdr1000_data ); KDE_DEBUG ("badflag (parity check) = %u\n", kdr1000_badflag); #endif if ((kdr1000_lrc == kdr1000_data) && (kdr1000_badflag == 0)) { KDE_DEBUG ("MSR callback\n"); hook_msr_kdr1000_read_call(kdr1000_buffer, kdr1000_digit); } kdr1000_end = 0; } kdr1000_lrc ^= kdr1000_data; } else { kdr1000_badflag = 1; } kdr1000_digit++; kdr1000_data = 0; kdr1000_parity=0x10; } kdr1000_data >>= 1; /* shift bits */ } } }