diff --git a/lib/onewire_master.c b/lib/onewire_master.c
new file mode 100644
index 0000000..c9c9c03
--- /dev/null
+++ b/lib/onewire_master.c
@@ -0,0 +1,492 @@
+/* This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+/** library for 1-wire protocol as master (code)
+ * @file onewire_master.c
+ * @author King Kévin
+ * @date 2017
+ * @note peripherals used: timer @ref onewire_master_timer, GPIO @ref onewire_master_gpio
+ * @warning this library does not support parasite power mode
+ */
+
+/* standard libraries */
+#include // standard integer types
+#include // boolean type
+#include // memory utilities
+
+/* STM32 (including CM3) libraries */
+#include // Cortex M3 utilities
+#include // interrupt handler
+#include // real-time control clock library
+#include // general purpose input output library
+#include // timer library
+
+/* own libraries */
+#include "global.h" // help macros
+#include "onewire_master.h" // own definitions
+
+/** @defgroup onewire_master_timer timer used to measure 1-wire signal timing
+ * @{
+ */
+#define ONEWIRE_MASTER_TIMER 2 /**< timer ID */
+/** @} */
+
+/** @defgroup onewire_master_gpio GPIO used for 1-wire signal
+ * @note use external pull-up resistor on pin
+ * @{
+ */
+#define ONEWIRE_MASTER_PORT A /**< GPIO port */
+#define ONEWIRE_MASTER_PIN 4 /**< GPIO pin */
+/** @} */
+
+/** state of 1-Wire communication */
+volatile enum {
+ ONEWIRE_STATE_IDLE, /**< no current communication */
+ ONEWIRE_STATE_DONE, /**< communication complete */
+ ONEWIRE_STATE_ERROR, /**< communication error */
+ ONEWIRE_STATE_MASTER_RESET, /**< reset pulse started */
+ ONEWIRE_STATE_SLAVE_PRESENCE, /**< waiting for slave response to reset pulse */
+ ONEWIRE_STATE_MASTER_WRITE, /**< master is writing bits */
+ ONEWIRE_STATE_MASTER_READ, /**< master is reading bits */
+ ONEWIRE_MAX /** to count the number of possible states */
+} onewire_master_state = ONEWIRE_STATE_IDLE;
+
+volatile bool slave_presence = false; /**< if slaves have been detected */
+uint8_t* buffer = NULL; /**< input/output buffer for read/write commands/functions */
+size_t buffer_size = 0; /**< size of buffer in bits */
+volatile size_t buffer_bit = 0; /**< number of bits read/written */
+
+void onewire_master_setup(void)
+{
+ // setup GPIO with external interrupt
+ rcc_periph_clock_enable(RCC_GPIO(ONEWIRE_MASTER_PORT)); // enable clock for GPIO peripheral
+ gpio_set_mode(GPIO(ONEWIRE_MASTER_PORT), GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO(ONEWIRE_MASTER_PIN)); // setup GPIO pin as output (master starts communication before slave replies)
+ gpio_set(GPIO(ONEWIRE_MASTER_PORT),GPIO(ONEWIRE_MASTER_PIN)); // idle is high (using pull-up resistor)
+
+ // setup timer to generate/measure signal timing
+ rcc_periph_clock_enable(RCC_TIM(ONEWIRE_MASTER_TIMER)); // enable clock for timer peripheral
+ timer_reset(TIM(ONEWIRE_MASTER_TIMER)); // reset timer state
+ timer_set_mode(TIM(ONEWIRE_MASTER_TIMER), TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); // set timer mode, use undivided timer clock, edge alignment (simple count), and count up
+ timer_set_prescaler(TIM(ONEWIRE_MASTER_TIMER), 1-1); // don't use prescale since this 16 bits timer allows to wait > 480 us used for the reset pulse ( 1/(72E6/1/(2**16))=910us )
+
+ // use comparator to time signal (without using the output), starting at slot start
+ timer_set_oc_value(TIM(ONEWIRE_MASTER_TIMER), TIM_OC1, 1*(rcc_ahb_frequency/1000000)); // use compare function to time master pulling low (1 < Tlowr < 15)
+ timer_set_oc_value(TIM(ONEWIRE_MASTER_TIMER), TIM_OC2, 7*(rcc_ahb_frequency/1000000)); // use compare function to read of write (1 < Trw < 15)
+ timer_set_oc_value(TIM(ONEWIRE_MASTER_TIMER), TIM_OC3, 62*(rcc_ahb_frequency/1000000)); // use compare function to end time slot (60 < Tslot < 120), this will be followed by a recovery time (end of timer)
+ timer_set_oc_value(TIM(ONEWIRE_MASTER_TIMER), TIM_OC4, 120*(rcc_ahb_frequency/1000000)); // use compare function to detect slave presence (60 < Tpdl < 240)
+
+ timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_UIF); // clear update (overflow) flag
+ timer_update_on_overflow(TIM(ONEWIRE_MASTER_TIMER)); // only use counter overflow as UEV source (use overflow as start time or timeout)
+ timer_enable_irq(TIM(ONEWIRE_MASTER_TIMER), TIM_DIER_UIE); // enable update interrupt for overflow
+ nvic_enable_irq(NVIC_TIM_IRQ(ONEWIRE_MASTER_TIMER)); // catch interrupt in service routine
+
+ slave_presence = false; // reset state
+ onewire_master_state = ONEWIRE_STATE_IDLE; // reset state
+}
+
+bool onewire_master_reset(void)
+{
+ // prepare timer
+ timer_disable_counter(TIM(ONEWIRE_MASTER_TIMER)); // disable timer to reconfigure it
+ timer_set_counter(TIM(ONEWIRE_MASTER_TIMER),0); // reset counter
+ timer_set_period(TIM(ONEWIRE_MASTER_TIMER), 490*(rcc_ahb_frequency/1000000)); // set timeout to > 480 us (490)
+
+ slave_presence = false; // reset state
+ onewire_master_state = ONEWIRE_STATE_MASTER_RESET; // set new state
+
+ gpio_clear(GPIO(ONEWIRE_MASTER_PORT),GPIO(ONEWIRE_MASTER_PIN)); // pull signal low to start reset (it's not important if it was low in the first place since the reset pulse has no maximum time)
+ timer_enable_counter(TIM(ONEWIRE_MASTER_TIMER)); // start timer
+
+ while (onewire_master_state!=ONEWIRE_STATE_DONE && onewire_master_state!=ONEWIRE_STATE_ERROR) { // wait until reset procedure completed
+ __WFI(); // go to sleep
+ }
+ if (ONEWIRE_STATE_ERROR==onewire_master_state) { // an error occurred
+ return false;
+ }
+
+ return slave_presence;
+}
+
+/** write bits on 1-Wire bus
+ * @warning buffer_size must be set to the number of bits to write and buffer must contain the data to write
+ * @return if write succeeded
+ */
+static bool onewire_master_write(void)
+{
+ buffer_bit = 0; // reset bit index
+ onewire_master_state = ONEWIRE_STATE_MASTER_WRITE; // set new state
+
+ // prepare timer
+ timer_disable_counter(TIM(ONEWIRE_MASTER_TIMER)); // disable timer to reconfigure it
+ timer_set_counter(TIM(ONEWIRE_MASTER_TIMER),0); // reset counter
+ timer_set_period(TIM(ONEWIRE_MASTER_TIMER), TIM_CCR3(TIM(ONEWIRE_MASTER_TIMER))+5*(rcc_ahb_frequency/1000000)); // set time for new time slot (Trec>1, after time slot end)
+ timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC2IF); // clear output compare flag
+ timer_enable_irq(TIM(ONEWIRE_MASTER_TIMER), TIM_DIER_CC2IE); // enable compare interrupt for bit setting
+ timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC3IF); // clear output compare flag
+ timer_enable_irq(TIM(ONEWIRE_MASTER_TIMER), TIM_DIER_CC3IE); // enable compare interrupt for end of time slow
+
+ // start writing
+ gpio_clear(GPIO(ONEWIRE_MASTER_PORT),GPIO(ONEWIRE_MASTER_PIN)); // pull signal low to start slot
+ timer_enable_counter(TIM(ONEWIRE_MASTER_TIMER)); // start timer
+ while (onewire_master_state!=ONEWIRE_STATE_DONE && onewire_master_state!=ONEWIRE_STATE_ERROR) { // wait until reset procedure completed
+ __WFI(); // go to sleep
+ }
+ if (ONEWIRE_STATE_ERROR==onewire_master_state) { // an error occurred
+ return false;
+ }
+ return true;
+}
+
+/** read bits on 1-Wire bus
+ * @warning buffer_size must be set to the number of bits to read
+ * @return if read succeeded
+ */
+static bool onewire_master_read(void)
+{
+ if (0==buffer_size) { // check input
+ return false;
+ }
+ if (!(buffer=realloc(buffer, (buffer_size-1)/8+1))) { // allocate memory
+ return false; // error in memory allocation
+ }
+ buffer_bit = 0; // reset bit index
+ onewire_master_state = ONEWIRE_STATE_MASTER_READ; // set new state
+
+ // prepare timer
+ timer_set_counter(TIM(ONEWIRE_MASTER_TIMER),0); // reset counter
+ timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC1IF); // clear output compare flag
+ timer_enable_irq(TIM(ONEWIRE_MASTER_TIMER), TIM_DIER_CC1IE); // enable compare interrupt for stop pulling low
+ timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC2IF); // clear output compare flag
+ timer_enable_irq(TIM(ONEWIRE_MASTER_TIMER), TIM_DIER_CC2IE); // enable compare interrupt for bit setting
+ timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC3IF); // clear output compare flag
+ timer_enable_irq(TIM(ONEWIRE_MASTER_TIMER), TIM_DIER_CC3IE); // enable compare interrupt for end of time slow
+
+ // start reading
+ gpio_clear(GPIO(ONEWIRE_MASTER_PORT),GPIO(ONEWIRE_MASTER_PIN)); // pull signal low to start slot
+ timer_enable_counter(TIM(ONEWIRE_MASTER_TIMER)); // start timer
+ while (onewire_master_state!=ONEWIRE_STATE_DONE && onewire_master_state!=ONEWIRE_STATE_ERROR) { // wait until reset procedure completed
+ __WFI(); // go to sleep
+ }
+ if (ONEWIRE_STATE_ERROR==onewire_master_state) { // an error occurred
+ return false;
+ }
+ return true;
+}
+
+uint8_t onewire_master_crc(uint8_t* data, size_t size)
+{
+ if (NULL==data || 0==size) { // check input
+ return 0; // wrong input
+ }
+
+ uint8_t crc = 0x00; // initial value
+ for (uint8_t i=0; i>1)^0x8C; // // shift to the right (for the next bit) and XOR with (reverse) polynomial
+ } else {
+ crc >>= 1; // just shift right (for the next bit)
+ }
+ }
+ }
+ return crc;
+}
+
+bool onewire_master_function_read(uint8_t function, uint8_t* data, size_t bits)
+{
+ // send function command
+ buffer_size = 8; // function command is only one byte
+ if (!(buffer=realloc(buffer, (buffer_size-1)/8+1))) { // allocate memory
+ return false; // error in memory allocation
+ }
+ buffer[0] = function; // set function command
+ if (!onewire_master_write()) { // send command
+ return false; // an error occurred
+ }
+
+ if (NULL==data || 0==bits) { // there is no data to read
+ return true; // operation completed
+ }
+
+ // read data
+ buffer_size = bits; // save number of bits to read
+ if (!onewire_master_read()) { // read bits from slave
+ return false; // an error occurred
+ }
+
+ // copy data to user buffer
+ for (uint8_t i=0; i=64) { // no previous conflict has been detected
+ *code = 0; // restart search codes
+ }
+
+ for (uint8_t bit=0; bit<64; bit++) { // go through all 64 bits ROM code
+ buffer_size = 2; // read two first bits to detect conflict
+ if (!onewire_master_read()) { // read ROM ID from slave
+ goto end; // an error occurred
+ }
+ switch (buffer[0]&0x03) { // check 2 bits received
+ case 0: // collision detected
+ if (bit==conflict_last) { // this conflict is known
+ *code |= (((uint64_t)1)<>bit); // set bit to send
+ if (!onewire_master_write()) { // send bit
+ goto end; // an error has occurred
+ }
+ }
+ // verify ROM code
+ uint8_t rom_code[8] = {0}; // to store ROM code
+ for (uint8_t i=0; i>(8*i); // split and save last code in ROM code
+ }
+ if (onewire_master_crc(rom_code, LENGTH(rom_code))) { // verify checksum
+ *code = 0; // return the last code found since it's valid
+ }
+
+end:
+ conflict_last = conflict_current; // update the last seen and unknown conflict
+ if (conflict_current<64) { // we have seen an unknown conflict
+ return true; // tell there are more slaves
+ } else { // no conflict seen
+ return false; // no more slaves
+ }
+}
+
+bool onewire_master_rom_skip(void)
+{
+ if (!onewire_master_function_write(0xcc, NULL, 0)) { // send SKIP ROM command
+ return false; // an error occurred
+ }
+ return true;
+}
+
+bool onewire_master_rom_match(uint64_t code)
+{
+ uint8_t rom_code[8] = {0}; // to store ROM code
+ for (uint8_t i=0; i>(8*i); // split and save code in ROM code
+ }
+ if (!onewire_master_function_write(0x55, rom_code, 64)) { // send MATCH ROM command with ROM code
+ return false; // an error occurred
+ }
+ return true;
+}
+
+
+/** interrupt service routine called for timer */
+void TIM_ISR(ONEWIRE_MASTER_TIMER)(void)
+{
+ if (timer_get_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_UIF)) { // overflow update event happened
+ timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_UIF); // clear flag
+ switch (onewire_master_state) {
+ case ONEWIRE_STATE_MASTER_RESET: // reset pulse has been started
+ timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC4IF); // clear output compare flag
+ timer_enable_irq(TIM(ONEWIRE_MASTER_TIMER), TIM_DIER_CC4IE); // enable compare interrupt for presence detection
+ gpio_set(GPIO(ONEWIRE_MASTER_PORT),GPIO(ONEWIRE_MASTER_PIN)); // set signal high again for slaves to respond
+ onewire_master_state = ONEWIRE_STATE_SLAVE_PRESENCE; // set new state
+ break;
+ case ONEWIRE_STATE_SLAVE_PRESENCE: // waiting for slave presence but none received
+ timer_disable_counter(TIM(ONEWIRE_MASTER_TIMER)); // disable timer
+ timer_disable_irq(TIM(ONEWIRE_MASTER_TIMER), TIM_DIER_CC4IE); // disable compare interrupt for presence detection
+ onewire_master_state = ONEWIRE_STATE_DONE; // go to next state
+ break;
+ case ONEWIRE_STATE_MASTER_READ: // end of time slot and recovery time for reading bit
+ case ONEWIRE_STATE_MASTER_WRITE: // end of time slot and recovery time for writing bit
+ if (buffer_bit.
+ *
+ */
+/** library for 1-wire protocol as master (API)
+ * @file onewire_master.c
+ * @author King Kévin
+ * @date 2017
+ * @note peripherals used: timer @ref onewire_master_timer, GPIO @ref onewire_master_gpio
+ * @warning this library does not support parasite power mode
+ */
+#pragma once
+
+/** setup 1-wire peripheral */
+void onewire_master_setup(void);
+/** send reset pulse
+ * @return if slaves have indicated their presence
+ */
+bool onewire_master_reset(void);
+/** compute CRC for 1-Wire
+ * @note this CRC-8 uses normal polynomial 0x31, reverse polynomial 0x8C, start value 0x00
+ * @param[in] data bytes on which to calculate CRC checksum on
+ * @param[in] size number of bytes in data
+ * @return computed CRC checksum
+ */
+uint8_t onewire_master_crc(uint8_t* data, size_t size);
+/** send READ ROM command
+ * @note user needs to send reset pulse before
+ * @return ROM code read
+ */
+uint64_t onewire_master_rom_read(void);
+/** send SEARCH ROM command
+ * @note user needs to send reset pulse before
+ * @warning undefined behaviour if a ROM code different than the last found is provided
+ * @param[in,out] code use 0 to start search ROM code from scratch, or last know value to search next; writes back next ROM code found, or 0 if error occurred
+ * @param[in] alarm search only for ROM codes for slaves with an alarm flag set
+ * @return if an additional slave has been detected
+ */
+bool onewire_master_rom_search(uint64_t* code, bool alarm);
+/** send SKIP ROM command (all slaves on the bus will be selected)
+ * @note user needs to send reset pulse before
+ * @return if operation succeeded
+ */
+bool onewire_master_rom_skip(void);
+/** send MATCH ROM command to select a specific slave
+ * @note user needs to send reset pulse before
+ * @param[in] code ROM code of slave to select
+ * @return if operation succeeded
+ */
+bool onewire_master_rom_match(uint64_t code);
+/** issue function and read data
+ * @note user needs to send a ROM command before
+ * @param[in] function function command to send
+ * @param[out] data buffer to save read bits (NULL if only the function command should be sent)
+ * @param[in] bits number of bits to read (0 if only the function command should be sent)
+ * @return if operation succeeded
+ */
+bool onewire_master_function_read(uint8_t function, uint8_t* data, size_t bits);
+/** issue function and write data
+ * @note user needs to send a ROM command before
+ * @param[in] function function command to send
+ * @param[out] data data to write (NULL if only the function command should be sent)
+ * @param[in] bits number of bits to write (0 if only the function command should be sent)
+ * @return if operation succeeded
+ */
+bool onewire_master_function_write(uint8_t function, uint8_t* data, size_t bits);