Compare commits

..

3 Commits

  1. 63
      .gitattributes
  2. 6
      .gitignore
  3. 112
      .vscode/c_cpp_properties.json
  4. 2
      LICENSE
  5. 36
      LowLevel.h
  6. 1
      OneWireIO.ino
  7. 32
      OneWireIO.sln
  8. 112
      OneWireIO.vcxproj
  9. 16
      OneWireIO.vcxproj.filters
  10. 19
      OneWireSlave.cpp
  11. 3
      OneWireSlave.h
  12. 16
      README.md
  13. 49
      TimerOne.cpp
  14. 355
      TimerOne.h
  15. 153
      config/known_16bit_timers.h
  16. 16
      examples/FakeDS18B20/README.md
  17. 83
      extras/documentation.md
  18. 34
      keywords.txt
  19. 9
      library.properties

63
.gitattributes vendored

@ -0,0 +1,63 @@
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain

6
.gitignore vendored

@ -0,0 +1,6 @@
/.vs
/Debug
/*.opensdf
/*.sdf
/*.opendb
/*.suo

112
.vscode/c_cpp_properties.json vendored

@ -1,112 +0,0 @@
{
"configurations": [
{
"name": "Mac",
"includePath": [
"/usr/include",
"/usr/local/include",
"/opt/arduino-1.8.5/hardware/arduino/avr/cores/arduino",
"/opt/arduino-1.8.5/hardware/tools/avr/avr/include",
"/opt/arduino-1.8.5/hardware/arduino/avr/variants/standard",
"${workspaceRoot}",
"${workspaceRoot}/src"
],
"defines": [
"ARDUINO=160",
"__AVR__",
"UBRRH",
"__AVR_ATmega328P__",
"VS_INTELLISENSE"
],
"intelliSenseMode": "clang-x64",
"browse": {
"path": [
"/usr/include",
"/usr/local/include",
"${workspaceRoot}"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
},
"macFrameworkPath": [
"/System/Library/Frameworks",
"/Library/Frameworks"
]
},
{
"name": "Linux",
"includePath": [
"/usr/include/c++/4.9",
"/usr/include/x86_64-linux-gnu/c++/4.9",
"/usr/include/c++/4.9/backward",
"/usr/lib/gcc/x86_64-linux-gnu/4.9/include",
"/usr/local/include",
"/usr/lib/gcc/x86_64-linux-gnu/4.9/include-fixed",
"/usr/include/x86_64-linux-gnu",
"/usr/include",
"/opt/arduino-1.8.5/hardware/arduino/avr/cores/arduino",
"/opt/arduino-1.8.5/hardware/tools/avr/avr/include",
"/opt/arduino-1.8.5/hardware/arduino/avr/variants/standard",
"${workspaceRoot}",
"${workspaceRoot}/src"
],
"defines": [
"ARDUINO=160",
"__AVR__",
"UBRRH",
"__AVR_ATmega328P__",
"VS_INTELLISENSE"
],
"intelliSenseMode": "clang-x64",
"browse": {
"path": [
"/usr/include/c++/4.9",
"/usr/include/x86_64-linux-gnu/c++/4.9",
"/usr/include/c++/4.9/backward",
"/usr/lib/gcc/x86_64-linux-gnu/4.9/include",
"/usr/local/include",
"/usr/lib/gcc/x86_64-linux-gnu/4.9/include-fixed",
"/usr/include/x86_64-linux-gnu",
"/usr/include",
"${workspaceRoot}"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
},
"compilerPath": "/usr/bin/gcc",
"cStandard": "c11",
"cppStandard": "c++14"
},
{
"name": "Win32",
"includePath": [
"C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/include",
"/opt/arduino-1.8.5/hardware/arduino/avr/cores/arduino",
"/opt/arduino-1.8.5/hardware/tools/avr/avr/include",
"/opt/arduino-1.8.5/hardware/arduino/avr/variants/standard",
"${workspaceRoot}",
"${workspaceRoot}/src"
],
"defines": [
"_DEBUG",
"UNICODE",
"_UNICODE",
"ARDUINO=160",
"__AVR__",
"UBRRH",
"__AVR_ATmega328P__",
"VS_INTELLISENSE"
],
"intelliSenseMode": "msvc-x64",
"browse": {
"path": [
"C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/include/*",
"${workspaceRoot}"
],
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": ""
}
}
],
"version": 3
}

2
LICENSE

@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2018 Youen Toupin, aka neuoy
Copyright (c) 2015 Youen Toupin, aka neuoy
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

36
src/utility/LowLevel.h → LowLevel.h

@ -4,10 +4,7 @@
#include <inttypes.h>
#ifdef VS_INTELLISENSE
#define __attribute__(...)
#define digitalPinToPort(pin) 0
#define digitalPinToBitMask(pin) 0
#define portInputRegister(arg1) 0
#define __attribute__()
#endif
#if ARDUINO >= 100
@ -30,39 +27,8 @@
#if defined (__AVR_ATtiny85__)
#define CLEARINTERRUPT GIFR |= (1 << INTF0)
#include "UserTimer.h" //ATtiny-support based on TinyCore1 Arduino-core for ATtiny at http://github.com/Coding-Badly/TinyCore1.git
__attribute__((always_inline)) static inline void UserTimer_Init( void )
{
UserTimer_SetToPowerup();
UserTimer_SetWaveformGenerationMode(UserTimer_(CTC_OCR));
}
__attribute__((always_inline)) static inline void UserTimer_Run(short skipTicks)
{
UserTimer_SetCount(0);
UserTimer_SetOutputCompareMatchAndClear(skipTicks);
UserTimer_ClockSelect(UserTimer_(Prescale_Value_64));
}
#define UserTimer_Stop() UserTimer_ClockSelect(UserTimer_(Stopped))
#elif defined (__AVR_ATmega328P__)
#define CLEARINTERRUPT EIFR |= (1 << INTF0)
#define USERTIMER_COMPA_vect TIMER1_COMPA_vect
__attribute__((always_inline)) static inline void UserTimer_Init( void )
{
TCCR1A = 0;
TCCR1B = 0;
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
}
__attribute__((always_inline)) static inline void UserTimer_Run(short skipTicks)
{
TCNT1 = 0;
OCR1A = skipTicks;
// turn on CTC mode with 64 prescaler
TCCR1B = (1 << WGM12) | (1 << CS11) | (1 << CS10);
}
#define UserTimer_Stop() TCCR1B = 0
#endif
#elif defined(__MK20DX128__) || defined(__MK20DX256__)

1
examples/FakeDS18B20/FakeDS18B20.ino → OneWireIO.ino

@ -1,4 +1,5 @@
#include "Arduino.h"
#include "LowLevel.h"
#include "OneWireSlave.h"
// This is the pin that will be used for one-wire data (depending on your arduino model, you are limited to a few choices, because some pins don't have complete interrupt support)

32
OneWireIO.sln

@ -0,0 +1,32 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.31101.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OneWireIO", "OneWireIO.vcxproj", "{3B500971-1570-460F-81C3-22AC3B7764B9}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|Mixed Platforms = Debug|Mixed Platforms
Debug|Win32 = Debug|Win32
Release|Any CPU = Release|Any CPU
Release|Mixed Platforms = Release|Mixed Platforms
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{3B500971-1570-460F-81C3-22AC3B7764B9}.Debug|Any CPU.ActiveCfg = Debug|Win32
{3B500971-1570-460F-81C3-22AC3B7764B9}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32
{3B500971-1570-460F-81C3-22AC3B7764B9}.Debug|Mixed Platforms.Build.0 = Debug|Win32
{3B500971-1570-460F-81C3-22AC3B7764B9}.Debug|Win32.ActiveCfg = Debug|Win32
{3B500971-1570-460F-81C3-22AC3B7764B9}.Debug|Win32.Build.0 = Debug|Win32
{3B500971-1570-460F-81C3-22AC3B7764B9}.Release|Any CPU.ActiveCfg = Release|Win32
{3B500971-1570-460F-81C3-22AC3B7764B9}.Release|Mixed Platforms.ActiveCfg = Release|Win32
{3B500971-1570-460F-81C3-22AC3B7764B9}.Release|Mixed Platforms.Build.0 = Release|Win32
{3B500971-1570-460F-81C3-22AC3B7764B9}.Release|Win32.ActiveCfg = Release|Win32
{3B500971-1570-460F-81C3-22AC3B7764B9}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

112
OneWireIO.vcxproj

@ -0,0 +1,112 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{3B500971-1570-460F-81C3-22AC3B7764B9}</ProjectGuid>
<RootNamespace>OneWireIO</RootNamespace>
<ProjectName>OneWireIO</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>D:\Outils\Arduino\hardware\arduino\avr\cores\arduino;D:\Outils\Arduino\hardware\tools\avr\avr\include;C:\Program Files %28x86%29\Arduino\hardware\arduino\avr\cores\arduino;C:\Program Files %28x86%29\Arduino\hardware\tools\avr\avr\include</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_MBCS;%(PreprocessorDefinitions);ARDUINO=160;__AVR__;UBRRH;__AVR_ATmega328P__;VS_INTELLISENSE</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<PostBuildEvent>
<Command>if exist $(ProjectDir)$(IntDir)$(ProjectName).ino.elf (
echo Elf generated
) else (
echo no output
exit /B 1
)</Command>
</PostBuildEvent>
<PostBuildEvent />
<CustomBuild>
<Command>
</Command>
</CustomBuild>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<CustomBuild Include="OneWireIO.ino">
<FileType>Document</FileType>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</ExcludedFromBuild>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">if exist $(ProjectDir)$(IntDir)$(ProjectName).ino.elf del $(ProjectDir)$(IntDir)$(ProjectName).ino.elf
"C:\Program Files (x86)\Arduino\arduino.exe" --upload --pref build.path=$(ProjectDir)$(Configuration) %(FullPath) | more
</Command>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">always_build_$(ProjectConfiguration).dummy</Outputs>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
</AdditionalInputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Building and uploading sketch...</Message>
</CustomBuild>
</ItemGroup>
<ItemGroup>
<ClCompile Include="OneWireSlave.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="TimerOne.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="config\known_16bit_timers.h" />
<ClInclude Include="LowLevel.h" />
<ClInclude Include="OneWireSlave.h" />
<ClInclude Include="TimerOne.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

16
OneWireIO.vcxproj.filters

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="OneWireSlave.cpp" />
<ClCompile Include="TimerOne.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="LowLevel.h" />
<ClInclude Include="OneWireSlave.h" />
<ClInclude Include="TimerOne.h" />
<ClInclude Include="config\known_16bit_timers.h" />
</ItemGroup>
<ItemGroup>
<CustomBuild Include="OneWireIO.ino" />
</ItemGroup>
</Project>

19
src/OneWireSlave.cpp → OneWireSlave.cpp

@ -1,4 +1,5 @@
#include "OneWireSlave.h"
#include "TimerOne.h"
// uncomment this line to enable sending messages along with errors (but takes more program memory)
//#define ERROR_MESSAGES
@ -68,9 +69,9 @@ void(*OneWireSlave::singleBitSentCallback_)(bool error);
void(*OneWireSlave::logCallback_)(const char* message);
ISR(USERTIMER_COMPA_vect) // timer1 interrupt
void timer1Interrupt()
{
UserTimer_Stop(); // disable clock
Timer1.detachInterrupt();
void(*event)() = timerEvent;
timerEvent = 0;
event();
@ -98,7 +99,8 @@ void OneWireSlave::begin(const byte* rom, byte pinNumber)
pin_.writeLow(); // make sure the internal pull-up resistor is disabled
// prepare hardware timer
UserTimer_Init();
Timer1.initialize(4);
Timer1.stop();
// start 1-wire activity
beginWaitReset_();
@ -234,16 +236,19 @@ byte OneWireSlave::crc8(const byte* data, short numBytes)
void OneWireSlave::setTimerEvent_(short delayMicroSeconds, void(*handler)())
{
delayMicroSeconds -= 10; // remove overhead (tuned on Arduino Uno)
if (delayMicroSeconds < 1)
delayMicroSeconds = 1;
short skipTicks = (delayMicroSeconds - 3) / 4; // round the micro seconds delay to a number of ticks to skip (4us per tick, so 4us must skip 0 tick, 8us must skip 1 tick, etc.)
if (skipTicks < 1) skipTicks = 1;
timerEvent = handler;
UserTimer_Run(skipTicks);
Timer1.attachInterrupt(timer1Interrupt);
Timer1.setPeriod(delayMicroSeconds);
Timer1.start();
}
void OneWireSlave::disableTimer_()
{
UserTimer_Stop();
Timer1.stop();
Timer1.detachInterrupt();
}
void OneWireSlave::onEnterInterrupt_()

3
src/OneWireSlave.h → OneWireSlave.h

@ -2,7 +2,7 @@
#define _OneWireSlave_h_
#include "Arduino.h"
#include "utility/LowLevel.h"
#include "LowLevel.h"
class OneWireSlave
{
@ -44,7 +44,6 @@ public:
//! Cancels any pending write operation, started by writeBit or write. If this function is called before the master asked for a bit, then nothing is sent to the master.
void stopWrite();
//! Sets the alarmed state, that is used when the master makes a conditional search of alarmed devices.
void alarmed(bool value);
static byte crc8(const byte* data, short numBytes);

16
README.md

@ -5,4 +5,18 @@ An arduino library to communicate using the Dallas one-wire protocol, where the
1-wire allows communication over long distances (100m and more, see Dallas documentation for details) with a single wire (plus a ground wire). You can put as much devices as you want on the same wire (they communicate one at a time). 1-wire also allows to send power over the data wire (parasitic power), but, though I haven't tried, I don't believe it would work with an Arduino. You'll need a separate 5V power source, which, if it comes next to your data wire, means you need 3 wires (5V, data, and ground). You'll also need a master controller, for example the USB adapter DS9490R, to connect to a computer, that will control communication with all 1-wire devices.
## How to use this library
Take a look at [the documentation of the library](extras/documentation.md)
This library allows you to emulate existing 1-wire devices with an Arduino, or to create your own protocol. All low-level details are handled by the library, such as reset detection, ROM matching, byte sending and receiving. Look at the demo sketch to see an example.
There are only 3 important functions:
- `void setReceiveCallback(void(*callback)(ReceiveEvent evt, byte data))` sets the function that will be called back when an event occurs, such as when a byte is received
- `void begin(byte* rom, byte pinNumber)` starts the library, which will respond to the provided ROM (must be unique on your network) on the specified Arduino pin. The ROM is cloned by the library, so you can discard your buffer immediately if you want.
- `void write(byte* bytes, short numBytes, void(*complete)(bool error))` starts writing one or more bytes, and will call the provided callback (optional) when it's done. The buffer you provide here must stay available until the end of the write operation, which happens in background. Do not use local variables.
## Notes about the interrupt-based implementation
Since the library is implemented using interrupts, none of its functions will block: you can continue execute your code immediately.
This also means callbacks are called from interrupt handlers, so you must make them very short to not block further communication.
You must also be careful when you explicitely block interrupts, as the 1-wire protocol has very tight timings, especially when writing bytes (which also happens when searching for device ROMs): a delay of 3 microseconds (yes, microseconds, not milliseconds) can be enough for some (quite intolerant) masters to miss a bit.
But if your code only blocks interrupts for reasonably short time, the probability to block exactly at the bad moment is low, so you can easily mitigate the issue by adding CRC checks in your high-level communication protocol, and retrying when an error is detected. This is an important thing to do anyway because 1-wire does not natively perform any error checking (excepted for ROM operations which already contain a CRC byte). Standard 1-wire devices also include CRC checks in their specific protocols.

49
TimerOne.cpp

@ -0,0 +1,49 @@
/*
* Interrupt and PWM utilities for 16 bit Timer1 on ATmega168/328
* Original code by Jesse Tane for http://labs.ideo.com August 2008
* Modified March 2009 by Jérôme Despatis and Jesse Tane for ATmega328 support
* Modified June 2009 by Michael Polli and Jesse Tane to fix a bug in setPeriod() which caused the timer to stop
* Modified Oct 2009 by Dan Clemens to work with timer1 of the ATMega1280 or Arduino Mega
* Modified April 2012 by Paul Stoffregen
* Modified again, June 2014 by Paul Stoffregen
* This version has been downloaded from https://github.com/PaulStoffregen/TimerOne (commit aaeb4a36f5f23e99e6011bea77cf76abb912e13a)
*
* This is free software. You can redistribute it and/or modify it under
* the terms of Creative Commons Attribution 3.0 United States License.
* To view a copy of this license, visit http://creativecommons.org/licenses/by/3.0/us/
* or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.
*
*/
#include "TimerOne.h"
TimerOne Timer1; // preinstatiate
unsigned short TimerOne::pwmPeriod = 0;
unsigned char TimerOne::clockSelectBits = 0;
void (*TimerOne::isrCallback)() = TimerOne::isrDefaultUnused;
// interrupt service routine that wraps a user defined function supplied by attachInterrupt
#if defined(__AVR__)
ISR(TIMER1_OVF_vect)
{
Timer1.isrCallback();
}
#elif defined(__arm__) && defined(CORE_TEENSY)
void ftm1_isr(void)
{
uint32_t sc = FTM1_SC;
#ifdef KINETISL
if (sc & 0x80) FTM1_SC = sc;
#else
if (sc & 0x80) FTM1_SC = sc & 0x7F;
#endif
Timer1.isrCallback();
}
#endif
void TimerOne::isrDefaultUnused()
{
}

355
TimerOne.h

@ -0,0 +1,355 @@
/*
* Interrupt and PWM utilities for 16 bit Timer1 on ATmega168/328
* Original code by Jesse Tane for http://labs.ideo.com August 2008
* Modified March 2009 by Jérôme Despatis and Jesse Tane for ATmega328 support
* Modified June 2009 by Michael Polli and Jesse Tane to fix a bug in setPeriod() which caused the timer to stop
* Modified April 2012 by Paul Stoffregen - portable to other AVR chips, use inline functions
* Modified again, June 2014 by Paul Stoffregen - support Teensy 3.x & even more AVR chips
* This version has been downloaded from https://github.com/PaulStoffregen/TimerOne (commit aaeb4a36f5f23e99e6011bea77cf76abb912e13a)
*
*
* This is free software. You can redistribute it and/or modify it under
* the terms of Creative Commons Attribution 3.0 United States License.
* To view a copy of this license, visit http://creativecommons.org/licenses/by/3.0/us/
* or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.
*
*/
#ifndef TimerOne_h_
#define TimerOne_h_
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include "config/known_16bit_timers.h"
#define TIMER1_RESOLUTION 65536UL // Timer1 is 16 bit
// Placing nearly all the code in this .h file allows the functions to be
// inlined by the compiler. In the very common case with constant values
// the compiler will perform all calculations and simply write constants
// to the hardware registers (for example, setPeriod).
class TimerOne
{
#if defined(__AVR__)
public:
//****************************
// Configuration
//****************************
void initialize(unsigned long microseconds=1000000) __attribute__((always_inline)) {
TCCR1B = _BV(WGM13); // set mode as phase and frequency correct pwm, stop the timer
TCCR1A = 0; // clear control register A
setPeriod(microseconds);
}
void setPeriod(unsigned long microseconds) __attribute__((always_inline)) {
const unsigned long cycles = (F_CPU / 2000000) * microseconds;
if (cycles < TIMER1_RESOLUTION) {
clockSelectBits = _BV(CS10);
pwmPeriod = cycles;
} else
if (cycles < TIMER1_RESOLUTION * 8) {
clockSelectBits = _BV(CS11);
pwmPeriod = cycles / 8;
} else
if (cycles < TIMER1_RESOLUTION * 64) {
clockSelectBits = _BV(CS11) | _BV(CS10);
pwmPeriod = cycles / 64;
} else
if (cycles < TIMER1_RESOLUTION * 256) {
clockSelectBits = _BV(CS12);
pwmPeriod = cycles / 256;
} else
if (cycles < TIMER1_RESOLUTION * 1024) {
clockSelectBits = _BV(CS12) | _BV(CS10);
pwmPeriod = cycles / 1024;
} else {
clockSelectBits = _BV(CS12) | _BV(CS10);
pwmPeriod = TIMER1_RESOLUTION - 1;
}
ICR1 = pwmPeriod;
TCCR1B = _BV(WGM13) | clockSelectBits;
}
//****************************
// Run Control
//****************************
void start() __attribute__((always_inline)) {
TCCR1B = 0;
TCNT1 = 0; // TODO: does this cause an undesired interrupt?
resume();
}
void stop() __attribute__((always_inline)) {
TCCR1B = _BV(WGM13);
}
void restart() __attribute__((always_inline)) {
start();
}
void resume() __attribute__((always_inline)) {
TCCR1B = _BV(WGM13) | clockSelectBits;
}
//****************************
// PWM outputs
//****************************
void setPwmDuty(char pin, unsigned int duty) __attribute__((always_inline)) {
unsigned long dutyCycle = pwmPeriod;
dutyCycle *= duty;
dutyCycle >>= 10;
if (pin == TIMER1_A_PIN) OCR1A = dutyCycle;
#ifdef TIMER1_B_PIN
else if (pin == TIMER1_B_PIN) OCR1B = dutyCycle;
#endif
#ifdef TIMER1_C_PIN
else if (pin == TIMER1_C_PIN) OCR1C = dutyCycle;
#endif
}
void pwm(char pin, unsigned int duty) __attribute__((always_inline)) {
if (pin == TIMER1_A_PIN) { pinMode(TIMER1_A_PIN, OUTPUT); TCCR1A |= _BV(COM1A1); }
#ifdef TIMER1_B_PIN
else if (pin == TIMER1_B_PIN) { pinMode(TIMER1_B_PIN, OUTPUT); TCCR1A |= _BV(COM1B1); }
#endif
#ifdef TIMER1_C_PIN
else if (pin == TIMER1_C_PIN) { pinMode(TIMER1_C_PIN, OUTPUT); TCCR1A |= _BV(COM1C1); }
#endif
setPwmDuty(pin, duty);
TCCR1B = _BV(WGM13) | clockSelectBits;
}
void pwm(char pin, unsigned int duty, unsigned long microseconds) __attribute__((always_inline)) {
if (microseconds > 0) setPeriod(microseconds);
pwm(pin, duty);
}
void disablePwm(char pin) __attribute__((always_inline)) {
if (pin == TIMER1_A_PIN) TCCR1A &= ~_BV(COM1A1);
#ifdef TIMER1_B_PIN
else if (pin == TIMER1_B_PIN) TCCR1A &= ~_BV(COM1B1);
#endif
#ifdef TIMER1_C_PIN
else if (pin == TIMER1_C_PIN) TCCR1A &= ~_BV(COM1C1);
#endif
}
//****************************
// Interrupt Function
//****************************
void attachInterrupt(void (*isr)()) __attribute__((always_inline)) {
isrCallback = isr;
TIMSK1 = _BV(TOIE1);
}
void attachInterrupt(void (*isr)(), unsigned long microseconds) __attribute__((always_inline)) {
if(microseconds > 0) setPeriod(microseconds);
attachInterrupt(isr);
}
void detachInterrupt() __attribute__((always_inline)) {
TIMSK1 = 0;
}
static void (*isrCallback)();
static void isrDefaultUnused();
private:
// properties
static unsigned short pwmPeriod;
static unsigned char clockSelectBits;
#elif defined(__arm__) && defined(CORE_TEENSY)
#if defined(KINETISK)
#define F_TIMER F_BUS
#elif defined(KINETISL)
#define F_TIMER (F_PLL/2)
#endif
public:
//****************************
// Configuration
//****************************
void initialize(unsigned long microseconds=1000000) __attribute__((always_inline)) {
setPeriod(microseconds);
}
void setPeriod(unsigned long microseconds) __attribute__((always_inline)) {
const unsigned long cycles = (F_TIMER / 2000000) * microseconds;
// A much faster if-else
// This is like a binary serch tree and no more than 3 conditions are evaluated.
// I haven't checked if this becomes significantly longer ASM than the simple ladder.
// It looks very similar to the ladder tho: same # of if's and else's
/*
// This code does not work properly in all cases :(
// https://github.com/PaulStoffregen/TimerOne/issues/17
if (cycles < TIMER1_RESOLUTION * 16) {
if (cycles < TIMER1_RESOLUTION * 4) {
if (cycles < TIMER1_RESOLUTION) {
clockSelectBits = 0;
pwmPeriod = cycles;
}else{
clockSelectBits = 1;
pwmPeriod = cycles >> 1;
}
}else{
if (cycles < TIMER1_RESOLUTION * 8) {
clockSelectBits = 3;
pwmPeriod = cycles >> 3;
}else{
clockSelectBits = 4;
pwmPeriod = cycles >> 4;
}
}
}else{
if (cycles > TIMER1_RESOLUTION * 64) {
if (cycles > TIMER1_RESOLUTION * 128) {
clockSelectBits = 7;
pwmPeriod = TIMER1_RESOLUTION - 1;
}else{
clockSelectBits = 7;
pwmPeriod = cycles >> 7;
}
}
else{
if (cycles > TIMER1_RESOLUTION * 32) {
clockSelectBits = 6;
pwmPeriod = cycles >> 6;
}else{
clockSelectBits = 5;
pwmPeriod = cycles >> 5;
}
}
}
*/
if (cycles < TIMER1_RESOLUTION) {
clockSelectBits = 0;
pwmPeriod = cycles;
} else
if (cycles < TIMER1_RESOLUTION * 2) {
clockSelectBits = 1;
pwmPeriod = cycles >> 1;
} else
if (cycles < TIMER1_RESOLUTION * 4) {
clockSelectBits = 2;
pwmPeriod = cycles >> 2;
} else
if (cycles < TIMER1_RESOLUTION * 8) {
clockSelectBits = 3;
pwmPeriod = cycles >> 3;
} else
if (cycles < TIMER1_RESOLUTION * 16) {
clockSelectBits = 4;
pwmPeriod = cycles >> 4;
} else
if (cycles < TIMER1_RESOLUTION * 32) {
clockSelectBits = 5;
pwmPeriod = cycles >> 5;
} else
if (cycles < TIMER1_RESOLUTION * 64) {
clockSelectBits = 6;
pwmPeriod = cycles >> 6;
} else
if (cycles < TIMER1_RESOLUTION * 128) {
clockSelectBits = 7;
pwmPeriod = cycles >> 7;
} else {
clockSelectBits = 7;
pwmPeriod = TIMER1_RESOLUTION - 1;
}
uint32_t sc = FTM1_SC;
FTM1_SC = 0;
FTM1_MOD = pwmPeriod;
FTM1_SC = FTM_SC_CLKS(1) | FTM_SC_CPWMS | clockSelectBits | (sc & FTM_SC_TOIE);
}
//****************************
// Run Control
//****************************
void start() __attribute__((always_inline)) {
stop();
FTM1_CNT = 0;
resume();
}
void stop() __attribute__((always_inline)) {
FTM1_SC = FTM1_SC & (FTM_SC_TOIE | FTM_SC_CPWMS | FTM_SC_PS(7));
}
void restart() __attribute__((always_inline)) {
start();
}
void resume() __attribute__((always_inline)) {
FTM1_SC = (FTM1_SC & (FTM_SC_TOIE | FTM_SC_PS(7))) | FTM_SC_CPWMS | FTM_SC_CLKS(1);
}
//****************************
// PWM outputs
//****************************
void setPwmDuty(char pin, unsigned int duty) __attribute__((always_inline)) {
unsigned long dutyCycle = pwmPeriod;
dutyCycle *= duty;
dutyCycle >>= 10;
if (pin == TIMER1_A_PIN) {
FTM1_C0V = dutyCycle;
} else if (pin == TIMER1_B_PIN) {
FTM1_C1V = dutyCycle;
}
}
void pwm(char pin, unsigned int duty) __attribute__((always_inline)) {
setPwmDuty(pin, duty);
if (pin == TIMER1_A_PIN) {
*portConfigRegister(TIMER1_A_PIN) = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE;
} else if (pin == TIMER1_B_PIN) {
*portConfigRegister(TIMER1_B_PIN) = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE;
}
}
void pwm(char pin, unsigned int duty, unsigned long microseconds) __attribute__((always_inline)) {
if (microseconds > 0) setPeriod(microseconds);
pwm(pin, duty);
}
void disablePwm(char pin) __attribute__((always_inline)) {
if (pin == TIMER1_A_PIN) {
*portConfigRegister(TIMER1_A_PIN) = 0;
} else if (pin == TIMER1_B_PIN) {
*portConfigRegister(TIMER1_B_PIN) = 0;
}
}
//****************************
// Interrupt Function
//****************************
void attachInterrupt(void (*isr)()) __attribute__((always_inline)) {
isrCallback = isr;
FTM1_SC |= FTM_SC_TOIE;
NVIC_ENABLE_IRQ(IRQ_FTM1);
}
void attachInterrupt(void (*isr)(), unsigned long microseconds) __attribute__((always_inline)) {
if(microseconds > 0) setPeriod(microseconds);
attachInterrupt(isr);
}
void detachInterrupt() __attribute__((always_inline)) {
FTM1_SC &= ~FTM_SC_TOIE;
NVIC_DISABLE_IRQ(IRQ_FTM1);
}
static void (*isrCallback)();
static void isrDefaultUnused();
private:
// properties
static unsigned short pwmPeriod;
static unsigned char clockSelectBits;
#undef F_TIMER
#endif
};
extern TimerOne Timer1;
#endif

153
config/known_16bit_timers.h

@ -0,0 +1,153 @@
#ifndef known_16bit_timers_header_
#define known_16bit_timers_header_
// Wiring-S
//
#if defined(__AVR_ATmega644P__) && defined(WIRING)
#define TIMER1_A_PIN 5
#define TIMER1_B_PIN 4
#define TIMER1_ICP_PIN 6
// Teensy 2.0
//
#elif defined(__AVR_ATmega32U4__) && defined(CORE_TEENSY)
#define TIMER1_A_PIN 14
#define TIMER1_B_PIN 15
#define TIMER1_C_PIN 4
#define TIMER1_ICP_PIN 22
#define TIMER1_CLK_PIN 11
#define TIMER3_A_PIN 9
#define TIMER3_ICP_PIN 10
// Teensy++ 2.0
#elif defined(__AVR_AT90USB1286__) && defined(CORE_TEENSY)
#define TIMER1_A_PIN 25
#define TIMER1_B_PIN 26
#define TIMER1_C_PIN 27
#define TIMER1_ICP_PIN 4
#define TIMER1_CLK_PIN 6
#define TIMER3_A_PIN 16
#define TIMER3_B_PIN 15
#define TIMER3_C_PIN 14
#define TIMER3_ICP_PIN 17
#define TIMER3_CLK_PIN 13
// Teensy 3.0
//
#elif defined(__MK20DX128__)
#define TIMER1_A_PIN 3
#define TIMER1_B_PIN 4
#define TIMER1_ICP_PIN 4
// Teensy 3.1 / Teensy 3.2
//
#elif defined(__MK20DX256__)
#define TIMER1_A_PIN 3
#define TIMER1_B_PIN 4
#define TIMER1_ICP_PIN 4
#define TIMER3_A_PIN 32
#define TIMER3_B_PIN 25
#define TIMER3_ICP_PIN 32
// Teensy 3.5 / Teensy 3.6
//
#elif defined(__MK64FX512__) || defined(__MK66FX1M0__)
#define TIMER1_A_PIN 3
#define TIMER1_B_PIN 4
#define TIMER1_ICP_PIN 4
#define TIMER3_A_PIN 29
#define TIMER3_B_PIN 30
#define TIMER3_ICP_PIN 29
// Teensy-LC
//
#elif defined(__MKL26Z64__)
#define TIMER1_A_PIN 16
#define TIMER1_B_PIN 17
#define TIMER1_ICP_PIN 17
#define TIMER3_A_PIN 3
#define TIMER3_B_PIN 4
#define TIMER3_ICP_PIN 4
// Arduino Mega
//
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#define TIMER1_A_PIN 11
#define TIMER1_B_PIN 12
#define TIMER1_C_PIN 13
#define TIMER3_A_PIN 5
#define TIMER3_B_PIN 2
#define TIMER3_C_PIN 3
#define TIMER4_A_PIN 6
#define TIMER4_B_PIN 7
#define TIMER4_C_PIN 8
#define TIMER4_ICP_PIN 49
#define TIMER5_A_PIN 46
#define TIMER5_B_PIN 45
#define TIMER5_C_PIN 44
#define TIMER3_ICP_PIN 48
#define TIMER3_CLK_PIN 47
// Arduino Leonardo, Yun, etc
//
#elif defined(__AVR_ATmega32U4__)
#define TIMER1_A_PIN 9
#define TIMER1_B_PIN 10
#define TIMER1_C_PIN 11
#define TIMER1_ICP_PIN 4
#define TIMER1_CLK_PIN 12
#define TIMER3_A_PIN 5
#define TIMER3_ICP_PIN 13
// Uno, Duemilanove, LilyPad, etc
//
#elif defined (__AVR_ATmega168__) || defined (__AVR_ATmega328P__)
#define TIMER1_A_PIN 9
#define TIMER1_B_PIN 10
#define TIMER1_ICP_PIN 8
#define TIMER1_CLK_PIN 5
// Sanguino
//
#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
#define TIMER1_A_PIN 13
#define TIMER1_B_PIN 12
#define TIMER1_ICP_PIN 14
#define TIMER1_CLK_PIN 1
// Wildfire - Wicked Devices
//
#elif defined(__AVR_ATmega1284P__) && defined(WILDFIRE_VERSION) && WILDFIRE_VERSION >= 3
#define TIMER1_A_PIN 5 // PD5
#define TIMER1_B_PIN 8 // PD4
#define TIMER1_ICP_PIN 6 // PD6
#define TIMER1_CLK_PIN 23 // PB1
#define TIMER3_A_PIN 12 // PB6
#define TIMER3_B_PIN 13 // PB7
#define TIMER3_ICP_PIN 9 // PB5
#define TIMER3_CLK_PIN 0 // PD0
#elif defined(__AVR_ATmega1284P__) && defined(WILDFIRE_VERSION) && WILDFIRE_VERSION < 3
#define TIMER1_A_PIN 5 // PD5
#define TIMER1_B_PIN 4 // PD4
#define TIMER1_ICP_PIN 6 // PD6
#define TIMER1_CLK_PIN 15 // PB1
#define TIMER3_A_PIN 12 // PB6
#define TIMER3_B_PIN 13 // PB7
#define TIMER3_ICP_PIN 11 // PB5
#define TIMER3_CLK_PIN 0 // PD0
// Mighty-1284 - Maniacbug
//
#elif defined(__AVR_ATmega1284P__)
#define TIMER1_A_PIN 12 // PD5
#define TIMER1_B_PIN 13 // PD4
#define TIMER1_ICP_PIN 14 // PD6
#define TIMER1_CLK_PIN 1 // PB1
#define TIMER3_A_PIN 6 // PB6
#define TIMER3_B_PIN 7 // PB7
#define TIMER3_ICP_PIN 5 // PB5
#define TIMER3_CLK_PIN 8 // PD0
#endif
#endif

16
examples/FakeDS18B20/README.md

@ -1,16 +0,0 @@
This is a **DS18B20** emulator, i.e. it turns an Arduino Uno into a device roughly equivalent to an actual DS18B20 temperature sensor. Excepted in this sample it doesn't actually sense temperature (because the Arduino lacks the hardware for this), it just returns 42 as if that was the expected answer.
To make it work, you will need to connect your Arduino Uno to a 1-wire master (for example an USB adapter on a computer).
You can then connect:
- a GND pin of your Uno to your 1-wire network ground.
- the pin "2" of your Uno to the data line of your 1-wire network. You may use "3" as well but need to change the code.
You will see 28.000000000002 probe that always return 42 as temperature :
$ cat 28.000000000002/temperature
42
Conversion timing is emulated as well.
If you don't use an Arduino Uno, you may need to adjust which pin you connect as the data line (it needs to have hardware interrupts), and make the corresponding change in the example source code. A few microcontrollers are compatible with the library, check the full list in [the documentation](../../extras/documentation.md).

83
extras/documentation.md

@ -1,83 +0,0 @@
# OneWireSlave library documentation
This library allows you to emulate existing 1-wire devices with an Arduino, or to create your own protocol. All low-level details are handled by the library, such as reset detection, ROM matching, byte sending and receiving. Look at the demo sketch to see an example.
## Compatible boards
If you have tested the library on another board, please send a pull-request (or just tell me which board) to update this list.
### ATmega328
- Arduino Uno (tested by [neuoy](https://github.com/neuoy))
## Getting started
See example "FakeDS18B20", and the associated [documentation](examples/FakeDS18B20/README.md), for a working use case of the library.
## Library reference
### setReceiveCallback
`void setReceiveCallback(void(*callback)(ReceiveEvent evt, byte data))`
Sets the function that will be called back when an event occurs, such as when a byte is received.
### begin
`void begin(byte* rom, byte pinNumber)`
Starts the library, which will respond to the provided ROM (must be unique on your network) on the specified Arduino pin. The ROM is cloned by the library, so you can discard your buffer immediately if you want.
### write
`bool write(const byte* bytes, short numBytes)`
Writes the specified bytes synchronously. This function blocks until the write operation has finished. Do not call from an interrupt handler! Returns true in case of success, false if an error occurs.
### beginWrite
`void beginWrite(const byte* bytes, short numBytes, void(*complete)(bool error))`
Starts sending the specified bytes. They will be sent in the background, and the buffer must remain valid and unchanged until the write operation has finished or is cancelled. The optional callback is used to notify when the bytes are sent, or if an error occured. Callbacks are executed from interrupts and should be as short as possible. If `bytes` is null or `numBytes` is 0, nothing is sent, which is equivalent to calling `stopWrite`. In any case, calling the write function will cancel the previous write operation if it didn't complete yet.
### setReceiveBitCallback
`void setReceiveBitCallback(void(*callback)(bool bit))`
Sets (or replaces) a function to be called when a bit is received. The byte reception callback is called after that if the received bit was the last of a byte. The callback is executed from interrupts and should be as short as possible. Failure to return quickly can prevent the library from correctly reading the next bit.
### writeBit
`bool writeBit(bool value)`
Writes a single bit synchronously. This function blocks until the bit is sent. Do not call from an interrupt handler! Returns true in case of success, false if an error occurs.
### beginWriteBit
`void beginWriteBit(bool value, bool repeat = false, void(*bitSent)(bool error) = 0)`
Sets a bit that will be sent next time the master asks for one. Optionnaly, the repeat parameter can be set to true to continue sending the same bit each time. In both cases, the send operation can be canceled by calling `stopWrite`.
### stopWrite
`void stopWrite()`
Cancels any pending write operation, started by writeBit or write. If this function is called before the master asked for a bit, then nothing is sent to the master.
### alarmed
`void alarmed(bool value)`
Sets the alarmed state, that is used when the master makes a conditional search of alarmed devices.
### setLogCallback(void(*callback)(const char* message))
`void setLogCallback(void(*callback)(const char* message))`
Sets (or replaces) a function to be called when the library has a message to log, if the functionality is enabled in OneWireSlave.cpp (uncomment line `#define ERROR_MESSAGES`). This is for debugging purposes.
### end
`void end()`
Stops all 1-wire activities, which frees hardware resources for other purposes.
## Notes about the interrupt-based implementation
Since the library is implemented using interrupts, none of its functions will block: you can continue execute your code immediately.
This also means callbacks are called from interrupt handlers, so you must make them very short to not block further communication.
You must also be careful when you explicitely block interrupts, as the 1-wire protocol has very tight timings, especially when writing bytes (which also happens when searching for device ROMs): a delay of 3 microseconds (yes, microseconds, not milliseconds) can be enough for some (quite intolerant) masters to miss a bit.
But if your code only blocks interrupts for reasonably short time, the probability to block exactly at the bad moment is low, so you can easily mitigate the issue by adding CRC checks in your high-level communication protocol, and retrying when an error is detected. This is an important thing to do anyway because 1-wire does not natively perform any error checking (excepted for ROM operations which already contain a CRC byte). Standard 1-wire devices also include CRC checks in their specific protocols.

34
keywords.txt

@ -1,34 +0,0 @@
#######################################
# Syntax Coloring Map For OneWireSlave
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
ReceiveEvent KEYWORD1
OneWireSlave KEYWORD1
Pin KEYWORD1
OWSlave KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
begin KEYWORD2
end KEYWORD2
setReceiveCallback KEYWORD2
setReceiveBitCallback KEYWORD2
write KEYWORD2
writeBit KEYWORD2
stopWrite KEYWORD2
alarmed KEYWORD2
crc8 KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
RE_Reset LITERAL1
RE_Byte LITERAL1
RE_Error LITERAL1

9
library.properties

@ -1,9 +0,0 @@
name=OneWireSlave
version=0.1
author=Youen Toupin, aka neuoy
maintainer=Youen Toupin, aka neuoy
sentence=Communicate using the Dallas one-wire protocol, where the Arduino takes the role of a slave.
paragraph=This library allows you to emulate existing 1-wire devices with an Arduino, or to create your own protocol. All low-level details are handled by the library, such as reset detection, ROM matching, byte sending and receiving.
category=Signal Input/Output
url=https://github.com/neuoy/OneWireArduinoSlave
architectures=*
Loading…
Cancel
Save