├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── maxim-crc8.c ├── maxim-crc8.h ├── onewire0.c ├── onewire0.h ├── test-delays.c └── test-harness.c /.gitignore: -------------------------------------------------------------------------------- 1 | *.d 2 | *.eep 3 | *.elf 4 | *.hex 5 | *.lss 6 | *.lst 7 | *.map 8 | *.o 9 | *.sym 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This package is the work of Nick Andrew and is not associated with Maxim Integrated nor Atmel. All code is licensed under the GNU General Public License, version 3. 2 | 3 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # @(#) Makefile for libonewire0.a 2 | 3 | MCU = attiny85 4 | 5 | # Optimization level, can be [0, 1, 2, 3, s]. 0 turns off optimization. 6 | # (Note: 3 is not always the best optimization level. See avr-libc FAQ.) 7 | OPT = s 8 | 9 | # Optional compiler flags. 10 | # -g: generate debugging information (for GDB, or for COFF conversion) 11 | # -O*: optimization level 12 | # -f...: tuning, see gcc manual and avr-libc documentation 13 | # -Wall...: warning level 14 | # -Wa,...: tell GCC to pass this to the assembler. 15 | # -ahlms: create assembler listing 16 | CFLAGS = -g -O$(OPT) \ 17 | -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums \ 18 | -Wall -Wstrict-prototypes \ 19 | -Wa,-adhlns=$(<:.c=.lst) \ 20 | $(patsubst %,-I%,$(EXTRAINCDIRS)) 21 | 22 | # Set a "language standard" compiler flag. 23 | # Unremark just one line below to set the language standard to use. 24 | # gnu99 = C99 + GNU extensions. See GCC manual for more information. 25 | CFLAGS += -std=gnu99 26 | 27 | # Combine all necessary flags and optional flags. 28 | # Add target processor to flags. 29 | ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) 30 | 31 | CC = avr-gcc 32 | 33 | # Compile: create object files from C source files. 34 | %.o : %.c 35 | @echo 36 | @echo Compiling $< 37 | $(CC) -c $(ALL_CFLAGS) $< -o $@ 38 | 39 | %.a: 40 | ar cru $@ $^ 41 | ranlib $@ 42 | 43 | # --------------------------------------------------------------------------- 44 | 45 | all: libonewire0.a 46 | 47 | clean: 48 | rm -f *.o libonewire0.a 49 | 50 | libonewire0.a: onewire0.o maxim-crc8.o 51 | 52 | onewire0.o: onewire0.c onewire0.h maxim-crc8.h 53 | maxim-crc8.o: maxim-crc8.c 54 | test-harness.o: test-harness.c onewire0.h 55 | test-delays.o: test-harness.c onewire0.h 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AVR ATTiny85 OneWire protocol library 2 | 3 | This library implements the Maxim 1-Wire protocol (see https://www.maximintegrated.com/en.html) on the AVR ATTiny85 microcontroller. 4 | 5 | As a software implementation of 1-Wire, it is unique, or at least novel, in that the tight timing requirements are implemented through the onboard timer device. It is a very accurate implementation of 1-Wire. 6 | 7 | This package is the work of Nick Andrew and is not associated with Maxim Integrated nor Atmel. All code is licensed under the GNU General Public License, version 3. 8 | 9 | ## Usage 10 | 11 | Two GPIO pins are in use, one for the 1-Wire protocol and the other one to enable a strong pullup (to provide power for passive powered devices). These pins are set at compile time. 12 | 13 | The 1-Wire pin defaults to PORTB4 and the strong pullup pin defaults to PORTB1. 14 | 15 | Only an 8 MHz CPU frequency is supported at present. Overdrive is not supported as the CPU is not fast enough. 16 | 17 | See `test-harness.c` for typical usage. 18 | 19 | The 1-Wire protocol is documented in Maxim Integrated Application Notes, including: 20 | * AN1796 "Overview of 1-Wire Technology and Its Use" 21 | * AN126 "1-Wire Communication Through Software" 22 | * AN187 "1-Wire Search Algorithm" 23 | * AN162 "Interfacing the DS18X20/DS1822 1-Wire® Temperature Sensor in a Microcontroller Environment" 24 | * Datasheets for the DS18B20 and DS18S20 digital thermometers 25 | * See https://www.maximintegrated.com/en/products/analog/sensors-and-sensor-interface/DS18B20.html 26 | 27 | ## Troubleshooting 28 | 29 | Compile test-harness.c and use a logic analyser to examine the output at all state transitions. 30 | -------------------------------------------------------------------------------- /maxim-crc8.c: -------------------------------------------------------------------------------- 1 | /* vim:sw=4:ts=4: 2 | ** 8-bit CRC calculation for 1-wire devices 3 | ** 4 | ** Code copied from AVR-Libc manual 5 | ** License: http://www.nongnu.org/avr-libc/LICENSE.txt (included by reference) 6 | ** 7 | ** See http://www.nongnu.org/avr-libc/user-manual/group__util__crc.html 8 | ** Also http://www.maxim-ic.com/appnotes.cfm/appnote_number/27 9 | */ 10 | 11 | #include "maxim-crc8.h" 12 | 13 | uint8_t crc8_update(uint8_t crc, uint8_t data) { 14 | uint8_t i; 15 | 16 | crc = crc ^ data; 17 | 18 | for (i = 0; i < 8; ++i) { 19 | if (crc & 0x01) { 20 | crc = (crc >> 1) ^ 0x8c; 21 | } else { 22 | crc >>= 1; 23 | } 24 | } 25 | 26 | return crc; 27 | } 28 | -------------------------------------------------------------------------------- /maxim-crc8.h: -------------------------------------------------------------------------------- 1 | /* vim:sw=4:ts=4: 2 | ** 8-bit CRC calculation for 1-wire devices 3 | */ 4 | 5 | #ifndef _MAXIM_CRC8_H 6 | #define _MAXIM_CRC8_H 7 | 8 | #include 9 | 10 | extern uint8_t crc8_update(uint8_t crc, uint8_t data); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /onewire0.c: -------------------------------------------------------------------------------- 1 | /* vim:sw=4:ts=4: 2 | ** 1-wire protocol library for ATTiny85 3 | ** (C) 2011, Nick Andrew 4 | ** All Rights Reserved. 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | #include "maxim-crc8.h" 13 | 14 | /* 15 | ** --------------------------------------------------------------------------- 16 | ** Pin and speed definitions 17 | ** --------------------------------------------------------------------------- 18 | */ 19 | 20 | // Specify the single I/O pin 21 | #ifndef PIN 22 | #define PIN ( 1 << PORTB4 ) 23 | #endif 24 | 25 | // Strong pullup is on PORTB1 (active low) 26 | #ifndef ONEWIRE_STRONG_PIN 27 | #define ONEWIRE_STRONG_PIN (PORTB1) 28 | #endif 29 | 30 | #ifndef CPU_FREQ 31 | #define CPU_FREQ 8000000 32 | #endif 33 | 34 | #if CPU_FREQ == 8000000 35 | // Prescaler CLKio/8 = 1 us resolution 36 | #define PRESCALER ( 1<> 3); 148 | bit_mask = 1 << (bit_id & 0x07); 149 | if (*cp & bit_mask) { 150 | return 1; 151 | } 152 | 153 | return 0; 154 | } 155 | 156 | // Set/Clear the value of a bit in a multi-byte array. 157 | // Bit numbers start from 1. 158 | 159 | static void _setbit(volatile uint8_t *cp, uint8_t bit_id, uint8_t value) 160 | { 161 | uint8_t bit_mask; 162 | 163 | bit_id --; 164 | // Point to the containing byte 165 | cp += (bit_id >> 3); 166 | bit_mask = 1 << (bit_id & 0x07); 167 | if (value) { 168 | *cp |= bit_mask; 169 | } else { 170 | *cp &= ~bit_mask; 171 | } 172 | } 173 | 174 | // Set a strong pullup on the 1-wire bus (active low) 175 | 176 | inline void _enable_strong(void) 177 | { 178 | PORTB &= ~(1 << ONEWIRE_STRONG_PIN); 179 | } 180 | 181 | // Disable a strong pullup (active low) 182 | 183 | inline void _disable_strong(void) { 184 | PORTB |= (1 << ONEWIRE_STRONG_PIN); 185 | } 186 | 187 | // Reset search 188 | static inline void _resetsearch(void) 189 | { 190 | search0.last_discrepancy = 0; 191 | search0.last_family_discrepancy = 0; 192 | search0.last_device_flag = 0; 193 | 194 | for (uint8_t i = 0; i < 8; ++i) { 195 | search0.device_id[i] = 0; 196 | } 197 | } 198 | 199 | void onewire0_init(void) 200 | { 201 | onewire0.state = OW0_IDLE; 202 | onewire0.process = OW0_PIDLE; 203 | _resetsearch(); 204 | 205 | // Setup pullup pin, mode output, initially disabled 206 | DDRB |= (1 << ONEWIRE_STRONG_PIN); 207 | _disable_strong(); 208 | // Setup I/O pin, initial tri-state, when enabled output low 209 | DDRB &= ~( PIN ); // Set pin mode to input 210 | PORTB &= ~( PIN ); // Disable weak pullup 211 | _starttimer(); 212 | } 213 | 214 | inline void _release(void) 215 | { 216 | _disable_strong(); 217 | PORTB &= ~( PIN ); // Disable weak pullup 218 | DDRB &= ~( PIN ); // Set pin mode to input 219 | } 220 | 221 | inline void _pulllow(void) 222 | { 223 | _disable_strong(); 224 | // PORTB is expected to be low at this point 225 | DDRB |= PIN; 226 | } 227 | 228 | static void _wait(void) 229 | { 230 | while (onewire0.state != OW0_IDLE) { } 231 | } 232 | 233 | static void _writebit(uint8_t value) 234 | { 235 | while (onewire0.state != OW0_IDLE) { } 236 | 237 | onewire0.current_byte = value ? 1 : 0; 238 | onewire0.bit_id = 1; 239 | onewire0.state = OW0_START; 240 | } 241 | 242 | static uint8_t _readbit(void) 243 | { 244 | while (onewire0.state != OW0_IDLE) { } 245 | 246 | onewire0.current_byte = 1; // Write a 1 bit to sample input 247 | onewire0.bit_id = 1; 248 | onewire0.state = OW0_START; 249 | 250 | while (onewire0.state != OW0_IDLE) { } 251 | 252 | return (onewire0.current_byte & 0x80) ? 1 : 0; 253 | } 254 | 255 | // Start to write 8 bits. 256 | // Wait for device to be idle before starting. 257 | // Do not wait for the bits to be sent. 258 | 259 | static void _write8(uint8_t byte) 260 | { 261 | while (onewire0.state != OW0_IDLE) { } 262 | 263 | onewire0.current_byte = byte; 264 | onewire0.bit_id = 8; 265 | onewire0.state = OW0_START; 266 | } 267 | 268 | // Start to read 8 bits. 269 | // Wait for device to be idle before starting. 270 | // Do not wait for the bits to arrive. 271 | 272 | static void _read8(void) 273 | { 274 | while (onewire0.state != OW0_IDLE) { } 275 | 276 | onewire0.current_byte = 0xff; // Write all 1-bits to sample input 8 times 277 | onewire0.bit_id = 8; 278 | onewire0.state = OW0_START; 279 | } 280 | 281 | // Start to read 2 bits. 282 | // Wait for device to be idle before starting. 283 | // Do not wait for the bits to arrive. 284 | 285 | static void _read2(void) 286 | { 287 | while (onewire0.state != OW0_IDLE) { } 288 | 289 | onewire0.current_byte = 0xff; // Write all 1-bits to sample input 2 times 290 | onewire0.bit_id = 2; 291 | onewire0.state = OW0_START; 292 | } 293 | 294 | /* void onewire0_writebyte(uint8_t byte) 295 | ** 296 | ** Write 8 bits to the bus. 297 | ** This function takes from 505us to 560us depending on idle state. 298 | ** It returns from 10us to 55us before the next time slot starts. 299 | */ 300 | 301 | void onewire0_writebyte(uint8_t byte) 302 | { 303 | _write8(byte); 304 | } 305 | 306 | /* uint8_t onewire0_readbyte() 307 | ** 308 | ** Read 8 bits from the bus and return the byte value. 309 | ** This function takes from 505us to 560us depending on idle state. 310 | ** It returns soon after sampling the last data bit, before the 311 | ** end of the last time slot. 312 | */ 313 | 314 | uint8_t onewire0_readbyte(void) 315 | { 316 | _read8(); 317 | 318 | while (onewire0.state != OW0_IDLE) { } 319 | 320 | return onewire0.current_byte; 321 | } 322 | 323 | /* void onewire0_reset(void) 324 | ** 325 | ** Reset devices on the bus. Wait for the reset process to complete. 326 | ** Return 1 if there are devices on the bus, else 0. 327 | */ 328 | 329 | uint8_t onewire0_reset(void) 330 | { 331 | while (onewire0.state != OW0_IDLE) { } 332 | 333 | onewire0.state = OW0_RESET; 334 | 335 | while (onewire0.state != OW0_IDLE) { } 336 | 337 | return (onewire0.current_byte & 0x80) ? 0 : 1; 338 | } 339 | 340 | /* void onewire0_delay1(uint8_t ocr0a, uint16_t usec1) 341 | ** 342 | ** Setup a delay for some number of microseconds. 343 | ** The delay = (ocr0a + 1) x usec1 x 1 us. 344 | ** The state will become OW0_IDLE after the programmed delay, but there 345 | ** will be another 20 us until the next interrupt. So take that into 346 | ** consideration. 347 | ** 348 | ** ocr0a = 0..255 as the number of counts per interrupt (minus 1) 349 | ** Values of ocr0a less than 10 or so won't work, as the interrupt handler 350 | ** takes around 10 us to process each interrupt. 351 | ** usec1 = 0..65535 as the number of interrupts (0 means 65536). 352 | ** 353 | ** Maximum sleep time = 65536 x 256 x 1 us = 16.777216 seconds. 354 | */ 355 | 356 | void onewire0_delay1(uint8_t ocr0a, uint16_t usec1) { 357 | while (onewire0.state != OW0_IDLE) { } 358 | 359 | onewire0.ocr0a = ocr0a; 360 | onewire0.delay_count = usec1; 361 | onewire0.state = OW0_DELAY1US; 362 | } 363 | 364 | /* void onewire0_delay8(uint8_t ocr0a, uint16_t usec8) 365 | ** 366 | ** Setup a delay for some number of microseconds. 367 | ** The delay = (ocr0a + 1) x usec8 x 8 us. 368 | ** The state will become OW0_IDLE after the programmed delay, but there 369 | ** will be another 20 us until the next interrupt. So take that into 370 | ** consideration. 371 | ** 372 | ** ocr0a = 0..255 as the number of counts per interrupt (minus 1) 373 | ** Values of ocr0a less than 2 won't work, as the interrupt handler 374 | ** takes around 10 us to process each interrupt. 375 | ** usec8 = 0..65535 as the number of interrupts (0 means 65536). 376 | ** 377 | ** Maximum sleep time = 65536 x 256 x 8 us = ~134 seconds. 378 | */ 379 | 380 | void onewire0_delay8(uint8_t ocr0a, uint16_t usec8) { 381 | while (onewire0.state != OW0_IDLE) { } 382 | 383 | onewire0.ocr0a = ocr0a; 384 | onewire0.delay_count = usec8; 385 | onewire0.state = OW0_DELAY8US; 386 | } 387 | 388 | /* void onewire0_delay128(uint8_t ocr0a, uint16_t usec128) 389 | ** 390 | ** Setup a delay for some number of microseconds. 391 | ** The delay = (ocr0a + 1) x usec128 x 128 us. 392 | ** The state will become OW0_IDLE after the programmed delay, but there 393 | ** will be another 20 us until the next interrupt. So take that into 394 | ** consideration. 395 | ** 396 | ** ocr0a = 0..255 as the number of counts per interrupt (minus 1) 397 | ** usec128 = 0..65535 as the number of interrupts (0 means 65536). 398 | ** 399 | ** Maximum sleep time = 65536 x 256 x 128 us = ~2147 seconds. 400 | */ 401 | 402 | void onewire0_delay128(uint8_t ocr0a, uint16_t usec128) { 403 | while (onewire0.state != OW0_IDLE) { } 404 | 405 | onewire0.ocr0a = ocr0a; 406 | onewire0.delay_count = usec128; 407 | onewire0.state = OW0_DELAY128US; 408 | } 409 | 410 | /* uint8_t onewire0_search(void) 411 | ** 412 | ** Initiate a 1wire device number search algorithm, 413 | ** and find the first 64-bit address. 414 | ** 415 | ** Return 1 if a device was found, 0 if no device. 416 | */ 417 | 418 | uint8_t onewire0_search(void) 419 | { 420 | uint8_t i; 421 | uint8_t id_bit_number = 1; 422 | 423 | if (!onewire0_reset() || search0.last_device_flag) { 424 | _resetsearch(); 425 | return 0; 426 | } 427 | 428 | search0.last_zero = 0; 429 | 430 | onewire0_writebyte(0xf0); 431 | 432 | while (id_bit_number <= 64) { 433 | uint8_t search_direction; 434 | 435 | _read2(); 436 | _wait(); 437 | 438 | // Pick top 2 bits of this byte only 439 | // bit 7 = cmp_id_bit 440 | // bit 6 = id_bit 441 | i = onewire0.current_byte & 0xc0; 442 | 443 | // if id_bit == cmp_id_bit == 1 444 | if (i == 0xc0) { 445 | // No device found 446 | _resetsearch(); 447 | return 0; 448 | } 449 | 450 | if (i == 0x00) { 451 | if (id_bit_number == search0.last_discrepancy) { 452 | search_direction = 1; 453 | } 454 | else if (id_bit_number > search0.last_discrepancy) { 455 | search_direction = 0; 456 | } 457 | else { 458 | // Set search_direction bit to id_bit_number bit in ROM_NO 459 | search_direction = _getbit(search0.device_id, id_bit_number); 460 | } 461 | 462 | if (search_direction == 0) { 463 | search0.last_zero = id_bit_number; 464 | if (search0.last_zero < 9) { 465 | search0.last_family_discrepancy = search0.last_zero; 466 | } 467 | } 468 | } else { 469 | search_direction = (i & 0x40) ? 1 : 0; 470 | } 471 | 472 | _setbit(search0.device_id, id_bit_number, search_direction); 473 | _writebit(search_direction); 474 | 475 | id_bit_number ++; 476 | } 477 | 478 | search0.last_discrepancy = search0.last_zero; 479 | 480 | if (search0.last_discrepancy == 0) { 481 | search0.last_device_flag = 1; 482 | } 483 | 484 | if (onewire0_check_crc((uint8_t *) search0.device_id, sizeof(search0.device_id))) { 485 | // Device ID fails CRC check; start over 486 | _resetsearch(); 487 | return 0; 488 | } 489 | 490 | return 1; 491 | } 492 | 493 | /* void onewire0_poll(void) 494 | ** 495 | ** Fast poll function. 496 | ** If the bus is busy, just return. 497 | ** If the bus is idle, then run more protocol if possible. 498 | */ 499 | 500 | void onewire0_poll(void) 501 | { 502 | if (onewire0.state != OW0_IDLE) { 503 | // Still going 504 | return; 505 | } 506 | 507 | switch(onewire0.process) { 508 | case OW0_PIDLE: 509 | // Do nothing 510 | break; 511 | } 512 | } 513 | 514 | // Prepare for the next bit of I/O. 515 | // If we're processing a byte, then go to state OW0_START for the next bit. 516 | // Otherwise, enter idle state upon next interrupt. 517 | 518 | static inline void _nextbit(void) { 519 | // Perform the next action in the meta-process 520 | if (--onewire0.bit_id) { 521 | // Continue reading/writing a byte with the next bit 522 | onewire0.state = OW0_START; 523 | } else { 524 | // The next state will be idle unless mainline code changes it 525 | // before the next interrupt (e.g. more bytes to send). 526 | onewire0.state = OW0_IDLE; 527 | } 528 | } 529 | 530 | // Interrupt routine for timer0, OCR0A 531 | 532 | ISR(TIMER0_COMPA_vect) 533 | { 534 | 535 | switch(onewire0.state) { 536 | case OW0_IDLE: 537 | // Wait 20us until the next interrupt 538 | OCR0A = IDLE_DELAY - 1; 539 | break; 540 | 541 | case OW0_START: 542 | _pulllow(); 543 | 544 | if (onewire0.current_byte & 1) { 545 | uint8_t delay; 546 | 547 | // Write a 1-bit or read a bit: 548 | // 6us low, 9us wait, sample, 55us high 549 | OCR0A = 70 - 1; 550 | 551 | // Delay 15 us within the interupt function: 552 | // 6 us signal low (48 instruction times) 553 | // This loop takes 5 x N instruction times 554 | for (delay = 0; delay < 8; ++delay) { 555 | asm("nop"); 556 | } 557 | 558 | // 9 us tri-state 559 | _release(); 560 | for (delay = 0; delay < 14; ++delay) { 561 | asm("nop"); 562 | } 563 | 564 | // shift byte then sample the signal 565 | onewire0.current_byte = (onewire0.current_byte >> 1) | ((PINB & (PIN)) ? 0x80 : 0); 566 | _nextbit(); 567 | } else { 568 | // Write a 0-bit 569 | // 60us low, 10us high 570 | OCR0A = GAP_C - 1; 571 | onewire0.state = OW0_RELEASE; 572 | onewire0.current_byte >>= 1; 573 | } 574 | 575 | break; 576 | 577 | case OW0_READWAIT: 578 | // Let the signal go high, wait 9us then sample. 579 | _release(); 580 | OCR0A = GAP_E - 1; 581 | onewire0.state = OW0_SAMPLE; 582 | break; 583 | 584 | case OW0_SAMPLE: 585 | // Bits are read from 0 to 7, which means we 586 | // have to shift current_byte down and store in bit 7 587 | // Shifting is done in state OW0_START so no need to do it again here. 588 | onewire0.current_byte |= ((PINB & (PIN)) ? 0x80 : 0); 589 | OCR0A = GAP_F - 1; 590 | _nextbit(); 591 | break; 592 | 593 | case OW0_RELEASE: 594 | // Let the signal go high for 10us. 595 | _release(); 596 | OCR0A = GAP_D + 5 - 1; 597 | _nextbit(); 598 | break; 599 | 600 | case OW0_RESET: 601 | // Pull the bus down and wait 480us (slow down the prescaler) 602 | _pulllow(); 603 | onewire0.ocr0a = GAP_H - 1; 604 | _medtimer(); 605 | onewire0.state = OW0_RESET1; 606 | break; 607 | 608 | case OW0_RESET1: 609 | // Release the bus, speed up the prescaler and wait for 9us 610 | _release(); 611 | OCR0A = GAP_I - 1; 612 | onewire0.state = OW0_RESET2; 613 | break; 614 | 615 | case OW0_RESET2: 616 | // Sample the bus, slow the prescaler down again and wait 408us 617 | onewire0.current_byte = ((PINB & (PIN)) ? 0x80 : 0); 618 | onewire0.ocr0a = GAP_J - 1; 619 | _medtimer(); 620 | onewire0.state = OW0_RESET3; 621 | break; 622 | 623 | case OW0_RESET3: 624 | // Speed up the prescaler again, go to idle state with 20us between interrupts 625 | OCR0A = IDLE_DELAY - 1; 626 | _fasttimer(); 627 | onewire0.state = OW0_IDLE; 628 | break; 629 | 630 | case OW0_DELAY1US: 631 | OCR0A = onewire0.ocr0a; 632 | // The timer is assumed to already be in fast mode 633 | onewire0.state = OW0_DELAY; 634 | break; 635 | 636 | case OW0_DELAY8US: 637 | // Setup timer to interrupt every 8 us x (ocr0a + 1), then enter delay loop 638 | _medtimer(); 639 | onewire0.state = OW0_DELAY; 640 | break; 641 | 642 | case OW0_DELAY128US: 643 | // Setup timer to interrupt every 128 us x (ocr0a + 1), then enter delay loop 644 | _delaytimer(); 645 | onewire0.state = OW0_DELAY; 646 | break; 647 | 648 | case OW0_DELAY: 649 | if (! --onewire0.delay_count) { 650 | // Delay is finished; setup the next interrupt in 20 us 651 | OCR0A = IDLE_DELAY - 1; 652 | _fasttimer(); 653 | onewire0.state = OW0_IDLE; 654 | } 655 | break; 656 | 657 | case OW0_DELAY_END: 658 | onewire0.state = OW0_IDLE; 659 | break; 660 | 661 | case OW0_CONVERT: 662 | // Program a 750 ms delay 663 | // 750ms = 1 us * 240 * 3125 664 | // 1000ms = 1 us * 250 * 4000 665 | OCR0A = 249; 666 | onewire0.delay_count = 4000; 667 | _enable_strong(); 668 | onewire0.state = OW0_CONVERT_DELAY; 669 | break; 670 | 671 | case OW0_CONVERT_DELAY: 672 | if (! --onewire0.delay_count) { 673 | // Delay is finished; setup the next interrupt in 20 us 674 | OCR0A = IDLE_DELAY - 1; 675 | _release(); 676 | onewire0.state = OW0_IDLE; 677 | } 678 | break; 679 | } 680 | 681 | 682 | // Return from interrupt 683 | } 684 | 685 | uint8_t onewire0_isidle(void) { 686 | return (onewire0.state == OW0_IDLE); 687 | } 688 | 689 | /* Return current device state. This is used for debugging. 690 | */ 691 | 692 | uint8_t onewire0_state(void) { 693 | return onewire0.state; 694 | } 695 | 696 | /* 697 | ** High Level Functions 698 | */ 699 | 700 | void onewire0_readrom(struct onewire_id *buf) { 701 | uint8_t *cp = buf->device_id; 702 | uint8_t byte_id; 703 | 704 | onewire0_writebyte(0x33); 705 | 706 | for (byte_id = 0; byte_id < 8; ++byte_id) { 707 | *cp++ = onewire0_readbyte(); 708 | } 709 | } 710 | 711 | void onewire0_matchrom(struct onewire_id *dev) { 712 | uint8_t *buf = dev->device_id; 713 | uint8_t byte_id; 714 | 715 | onewire0_writebyte(0x55); 716 | 717 | for (byte_id = 0; byte_id < 8; ++byte_id) { 718 | onewire0_writebyte(*buf++); 719 | } 720 | } 721 | 722 | void onewire0_skiprom(void) { 723 | onewire0_writebyte(0xcc); 724 | } 725 | 726 | void onewire0_readscratchpad(void) { 727 | onewire0_writebyte(0xbe); 728 | } 729 | 730 | // Issue 0x44, "Convert T". 731 | 732 | void onewire0_convert(void) { 733 | onewire0_writebyte(0x44); 734 | } 735 | 736 | void onewire0_convertdelay(void) { 737 | while (onewire0.state != OW0_IDLE) { } 738 | // Start the strong pullup (will be reset on next call to _pulllow) 739 | _enable_strong(); 740 | // Start a 750 ms delay, with a strong pullup to power the chips 741 | onewire0.state = OW0_CONVERT; 742 | } 743 | 744 | void onewire0_writescratch(char *scratch) { 745 | uint8_t byte_id; 746 | 747 | onewire0_writebyte(0x4e); 748 | 749 | for (byte_id = 0; byte_id < 3; ++byte_id) { 750 | onewire0_writebyte(*scratch++); 751 | } 752 | } 753 | 754 | uint8_t onewire0_readpower(void) { 755 | onewire0_writebyte(0xb4); 756 | 757 | return _readbit(); 758 | } 759 | 760 | uint8_t onewire0_get_family_code(struct onewire_id *dev) { 761 | return dev->device_id[0]; 762 | } 763 | 764 | /* Check an array of bytes using the Maxim 8-bit CRC algorithm. 765 | ** The last byte must be the expected CRC to make the final 766 | ** result zero. 767 | */ 768 | 769 | uint8_t onewire0_check_crc(uint8_t *cp, uint8_t length) { 770 | uint8_t crc = 0x00; 771 | 772 | while (length--) { 773 | crc = crc8_update(crc, *cp++); 774 | } 775 | 776 | return crc; 777 | } 778 | -------------------------------------------------------------------------------- /onewire0.h: -------------------------------------------------------------------------------- 1 | /* vim:sw=4:ts=4: 2 | ** 1-wire protocol library for ATTiny85 3 | ** (C) 2011, Nick Andrew 4 | ** All Rights Reserved. 5 | */ 6 | 7 | #ifndef _ONEWIRE_H_ 8 | #define _ONEWIRE_H_ 9 | 10 | #include 11 | 12 | /* 13 | ** 1wire signal timing, in microseconds unless otherwise noted 14 | ** 15 | ** GAP_A Write 1 bit bus low and Read bit bus low 16 | ** GAP_B Write 1 bit release bus 17 | ** GAP_C Write 0 bit bus low 18 | ** GAP_D Write 0 bit release bus 19 | ** GAP_E Read bit release bus 20 | ** GAP_F Read bit after sampling 21 | ** GAP_G Reset devices initial delay (zero so not used) 22 | ** GAP_H Reset devices bus low (divided by 8) 23 | ** GAP_I Reset devices release bus (divided by 8) 24 | ** GAP_J Reset devices delay after sampling (divided by 8) 25 | */ 26 | 27 | #define GAP_A 6 28 | #define GAP_B 64 29 | #define GAP_C 60 30 | #define GAP_D 10 31 | #define GAP_E 9 32 | #define GAP_F 55 33 | #define GAP_G 0 34 | #define GAP_H 60 35 | #define GAP_I 9 36 | #define GAP_J 51 37 | 38 | enum onewire0_state { 39 | OW0_IDLE, // Bus is currently idle or timeslot still finishing 40 | OW0_START, // Next interrupt begins a timeslot 41 | OW0_READWAIT, // Wait 9us before sampling bus 42 | OW0_SAMPLE, // Sample bus then go to idle for 55us 43 | OW0_RELEASE, // Pullup bus then go to idle for 10us 44 | OW0_RESET, // Pulldown bus for 480us to reset all devices 45 | OW0_RESET1, 46 | OW0_RESET2, 47 | OW0_RESET3, 48 | OW0_DELAY1US, // Start delay countdown at 1 us per timer count 49 | OW0_DELAY8US, // Start delay countdown at 8 us per timer count 50 | OW0_DELAY128US, // Start delay countdown at 128 us per timer count 51 | OW0_DELAY, 52 | OW0_DELAY_END, // Reset the timer after an 8 us or 128 us delay operation 53 | 54 | // For conversion delays 55 | OW0_CONVERT, // Start 750ms delay with strong pullup 56 | OW0_CONVERT_DELAY, 57 | }; 58 | 59 | enum onewire0_process { 60 | OW0_PIDLE, 61 | }; 62 | 63 | struct onewire { 64 | volatile enum onewire0_state state; 65 | volatile uint8_t current_byte; 66 | volatile uint8_t bit_id; 67 | volatile enum onewire0_process process; 68 | volatile uint8_t ocr0a; 69 | volatile uint16_t delay_count; 70 | }; 71 | 72 | struct onewire_id { 73 | uint8_t device_id[8]; 74 | }; 75 | 76 | // These are for the device ID search algorithm 77 | 78 | struct onewire_search { 79 | volatile uint8_t device_id[8]; 80 | volatile uint8_t last_discrepancy; 81 | volatile uint8_t last_family_discrepancy; 82 | volatile uint8_t last_device_flag; 83 | volatile uint8_t last_zero; 84 | }; 85 | 86 | struct onewire_scratchpad { 87 | uint8_t temp_lsb; 88 | uint8_t temp_msb; 89 | uint8_t t_h; 90 | uint8_t t_l; 91 | uint8_t config; 92 | uint8_t reserved_1; 93 | uint8_t reserved_2; 94 | uint8_t reserved_3; 95 | uint8_t crc; 96 | }; 97 | 98 | extern void onewire0_init(void); 99 | extern void onewire0_poll(void); 100 | extern uint8_t onewire0_readbyte(void); 101 | extern uint8_t onewire0_reset(void); 102 | extern uint8_t onewire0_search(void); 103 | extern void onewire0_writebyte(uint8_t byte); 104 | extern uint8_t onewire0_isidle(void); 105 | extern uint8_t onewire0_state(void); 106 | 107 | // Delay functions 108 | extern void onewire0_convertdelay(void); 109 | extern void onewire0_delay1(uint8_t ocr0a, uint16_t usec1); 110 | extern void onewire0_delay8(uint8_t ocr0a, uint16_t usec8); 111 | extern void onewire0_delay128(uint8_t ocr0a, uint16_t usec128); 112 | 113 | // OneWire high level functions 114 | 115 | extern void onewire0_readrom(struct onewire_id *buf); 116 | extern void onewire0_matchrom(struct onewire_id *buf); 117 | extern void onewire0_skiprom(void); 118 | extern void onewire0_convert(void); 119 | extern void onewire0_readscratchpad(void); 120 | extern uint8_t onewire0_get_family_code(struct onewire_id *dev); 121 | extern uint8_t onewire0_check_crc(uint8_t *cp, uint8_t length); 122 | 123 | #endif 124 | -------------------------------------------------------------------------------- /test-delays.c: -------------------------------------------------------------------------------- 1 | /* vim:sw=4:ts=4: 2 | ** 3 | ** Test the 1wire library - delays 4 | ** 5 | ** (C) 2011, Nick Andrew 6 | ** All Rights Reserved. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "onewire0.h" 14 | 15 | struct onewire_id device_id; 16 | 17 | // Connect a logic analyzer to these pins for tracing execution and timing 18 | #define DPINA (1 << PORTB1) 19 | #define DPINB (1 << PORTB2) 20 | #define DPINC (1 << PORTB3) 21 | 22 | /* Set highest frequency CPU operation 23 | ** Startup frequency is assumed to be 1 MHz 24 | ** 8 MHz for the internal clock 25 | */ 26 | 27 | void set_cpu_8mhz(void) { 28 | // Let's wind this sucker up to 8 MHz 29 | CLKPR = 1< 6 | ** All Rights Reserved. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "onewire0.h" 14 | 15 | struct onewire_id device_id; 16 | 17 | // Connect a logic analyzer to these pins for tracing execution and timing 18 | #define DPINB (1 << PORTB2) 19 | #define DPINC (1 << PORTB3) 20 | 21 | /* Set highest frequency CPU operation 22 | ** Startup frequency is assumed to be 1 MHz 23 | ** 8 MHz for the internal clock 24 | */ 25 | 26 | void set_cpu_8mhz(void) { 27 | // Let's wind this sucker up to 8 MHz 28 | CLKPR = 1<