Help with Platform I/o definitions on arduino

Hi please I'm trying to reverse engineer and understand how onewire library implementation works on arduino as i'm looking forward to make a UART onewire implementation. it's been really tough almost all night trying to catch up with definitions on header files from one place to another.. so I'm asking for help if someone can please help me out understand what do these definitions mean

Onewire.h code.

//[b] Platform specific I/O definitions

#if defined(__AVR__)
#define PIN_TO_BASEREG(pin)             (portInputRegister(digitalPinToPort(pin)))
#define PIN_TO_BITMASK(pin)             (digitalPinToBitMask(pin))         <=== this is the only one I understand sets the bitmask
                                                                                                                                           from a specific pin from pins_arduino.h
#define IO_REG_TYPE uint8_t
#define IO_REG_ASM asm("r30")
#define DIRECT_READ(base, mask)         (((*(base)) & (mask)) ? 1 : 0)
#define DIRECT_MODE_INPUT(base, mask)   ((*((base)+1)) &= ~(mask))
#define DIRECT_MODE_OUTPUT(base, mask)  ((*((base)+1)) |= (mask))
#define DIRECT_WRITE_LOW(base, mask)    ((*((base)+2)) &= ~(mask))
#define DIRECT_WRITE_HIGH(base, mask)   ((*((base)+2)) |= (mask))

[/b]

I'm trying to understand how they work together with onewire.cpp, for instance with this piece of code at least help me understand the reset from all line initialization steps from onewire

OneWire::OneWire(uint8_t pin)

{
	pinMode(pin, INPUT);
	bitmask = PIN_TO_BITMASK(pin);  <<<=== I know this brings up the bitmask corresponding to the arduino pin 
                                                                              for instance digital pin 13 brings   0b00100000. [/b]

	baseReg = PIN_TO_BASEREG(pin);  <<== I don't understand what this brings up to basereg
	
#if ONEWIRE_SEARCH
	reset_search();
#endif
}


// Perform the onewire reset function.  We will wait up to 250uS for
// the bus to come high, if it doesn't then it is broken or shorted
// and we return a 0;
//
// Returns 1 if a device asserted a presence pulse, 0 otherwise.
//

uint8_t OneWire::reset(void)
{
	IO_REG_TYPE mask = bitmask;  <<==bitmask if digital pin 13 is set here 
                                                                                   IO_REG_TYPE  is 0b00100000 ? right?
	
        volatile IO_REG_TYPE *reg IO_REG_ASM = baseReg;      <<== Lost here what does *reg mean 
	uint8_t r;
	uint8_t retries = 125;

	noInterrupts();                                                   
	DIRECT_MODE_INPUT(reg, mask);    <==== lost here as well about DIRECT_MODE_INPUT and reg mask
	interrupts();

	// wait until the wire is high... just in case    <== I know it's trying to set up the line low for a time slot of 480us but 
                                                                                          hardly understand the syntax.
	do {
		if (--retries == 0) return 0;
		delayMicroseconds(2);
	} while ( !DIRECT_READ(reg, mask));

	noInterrupts();
	DIRECT_WRITE_LOW(reg, mask);
	DIRECT_MODE_OUTPUT(reg, mask);	// drive output low
	interrupts();
	delayMicroseconds(480);             <<=== this is setting line low to 480us right?
	noInterrupts();
	DIRECT_MODE_INPUT(reg, mask);	// allow it to float
	delayMicroseconds(70);           <==== 70us for presence ? 
	r = !DIRECT_READ(reg, mask);
	interrupts();
	delayMicroseconds(410);
	return r;
}
#define PIN_TO_BASEREG(pin)             (portInputRegister(digitalPinToPort(pin)))
	bitmask = PIN_TO_BITMASK(pin);  <<<=== I know this brings up the bitmask corresponding to the arduino pin 
                                                                              for instance digital pin 13 brings   0b00100000. [/b]

	baseReg = PIN_TO_BASEREG(pin);  <<== I don't understand what this brings up to basereg

You know an Arduino pin number, so you need to identify both the register AND the bit within the register the pin maps to.

volatile IO_REG_TYPE *baseReg;
#define IO_REG_TYPE uint8_t

So, a pointer to a memory-mapped register.

#define DIRECT_READ(base, mask)         (((*(base)) & (mask)) ? 1 : 0)
#define DIRECT_MODE_INPUT(base, mask)   ((*(base+1)) &= ~(mask))
#define DIRECT_MODE_OUTPUT(base, mask)  ((*(base+1)) |= (mask))
#define DIRECT_WRITE_LOW(base, mask)    ((*(base+2)) &= ~(mask))
#define DIRECT_WRITE_HIGH(base, mask)   ((*(base+2)) |= (mask))

The AVRs have three registers per I/O port - PORT, DDR, PIN at consecutive addresses.

AWOL:

#define PIN_TO_BASEREG(pin)             (portInputRegister(digitalPinToPort(pin)))
	bitmask = PIN_TO_BITMASK(pin);  <<<=== I know this brings up the bitmask corresponding to the arduino pin 

for instance digital pin 13 brings   0b00100000. [/b]

baseReg = PIN_TO_BASEREG(pin);  <<== I don't understand what this brings up to basereg



You know an Arduino pin number, so you need to identify both the register AND the bit within the register the pin maps to.



volatile IO_REG_TYPE *baseReg;





#define IO_REG_TYPE uint8_t




So, a pointer to a memory-mapped register.

Hi thanks can you explain it more graphically with an example, say for instance I set up the following code to use a one wire DS18B20 temp sensor. Just the first line of code.

#include <Onewire.h>
OneWire ds(10); // I instantiate object DS from onewire library on digital pin 10 how does this translate to the code I pasted before.

It depends on which board you're using - that's why the code is written like it is.

AWOL:
It depends on which board you're using - that's why the code is written like it is.

Hi sorry I was kind of busy, I just saw your answer. Im using an arduino uno r3. Can you guide me a bit using the example I gave so I can follow step by step what basereg value is and bitmask as well. Also about the reset routine.
Thanks so much

It's difficult to guide someone when you don't know what part of the path they can't see.
You have all the source, so you can see everything I can see.

AWOL:
It's difficult to guide someone when you don't know what part of the path they can't see.
You have all the source, so you can see everything I can see.

Hi sorry for the late response. I do know quite clear the whole path you're talking about . My question was pointing out towards those definitions which I didn't understand how they related in low level. As I'm not that savvy how all headers relate to the arduino platform itself.
So i was trying to understand how the one wire protocol worked as I wanted to make a UART implementation. Problem was I did find a couple places with UART one wire implementation mostly cause it's used for it's slot precise timings. Like people from electric imp for instance. Implementing 1-Wire Buses In imp-enabled Devices | Dev Center , there you can see how they're implementing the a one wire master through UART, that's basically what I wanted to do with arduino UART.
So I started reading the whole onewire library to understand the reset, search, write routines. How they work when you define a one wire object in a digital pin 10 and how this all goes through the one wire protocol routine. Here I'm talking about how they're assigned values starting up with. Basically what I'm asking is you to provide me an example as to know how it goes thorugh the onewire library , so for instance if you define in a sketch

#include <onewire.h>
OneWire ds(10); <<== how does 10 as an argument defining the pin number translates below.

The same applies to the I/O definitions there are some definitions I don't understand cause I couldn't pin point them precisely how arduino uses them internally. For instance talking about a specific I/o definition like this one
#define DIRECT_READ(base, mask) ((((base)) & (mask)) ? 1 : 0) What does this mean ((((base)) & (mask)) ? 1 : 0)

What's *(base) & (mask) I understand here it's a bitwise operation and'ing base with a mask , then ? 1: 0 what does it mean?

//[b] Platform specific I/O definitions

#if defined(__AVR__)
#define PIN_TO_BASEREG(pin)             (portInputRegister(digitalPinToPort(pin)))
#define PIN_TO_BITMASK(pin)             (digitalPinToBitMask(pin))         <=== this is the only one I understand sets the bitmask
                                                                                                                                           from a specific pin from pins_arduino.h
#define IO_REG_TYPE uint8_t
#define IO_REG_ASM asm("r30")
#define DIRECT_READ(base, mask)         (((*(base)) & (mask)) ? 1 : 0)
#define DIRECT_MODE_INPUT(base, mask)   ((*((base)+1)) &= ~(mask))
#define DIRECT_MODE_OUTPUT(base, mask)  ((*((base)+1)) |= (mask))
#define DIRECT_WRITE_LOW(base, mask)    ((*((base)+2)) &= ~(mask))
#define DIRECT_WRITE_HIGH(base, mask)   ((*((base)+2)) |= (mask))

OneWire::OneWire(uint8_t pin)

{
pinMode(pin, INPUT);
bitmask = PIN_TO_BITMASK(pin); <<<=== I know this brings up the bitmask corresponding to the arduino pin
for instance digital pin 13 brings 0b00100000. [/b]

baseReg = PIN_TO_BASEREG(pin); <<== I don't understand what this brings up to basereg

#if ONEWIRE_SEARCH
reset_search();
#endif
}

// Perform the onewire reset function. We will wait up to 250uS for
// the bus to come high, if it doesn't then it is broken or shorted
// and we return a 0;
//
// Returns 1 if a device asserted a presence pulse, 0 otherwise.
//

uint8_t OneWire::reset(void)
{
IO_REG_TYPE mask = bitmask; <<==bitmask if digital pin 13 is set here
IO_REG_TYPE is 0b00100000 ? right?

volatile IO_REG_TYPE *reg IO_REG_ASM = baseReg; <<== Lost here what does *reg mean
uint8_t r;
uint8_t retries = 125;

noInterrupts();
DIRECT_MODE_INPUT(reg, mask); <==== lost here as well about DIRECT_MODE_INPUT and reg mask
interrupts();

// wait until the wire is high... just in case <== I know it's trying to set up the line low for a time slot of 480us but
hardly understand the syntax.
do {
if (--retries == 0) return 0;
delayMicroseconds(2);
} while ( !DIRECT_READ(reg, mask));

noInterrupts();
DIRECT_WRITE_LOW(reg, mask);
DIRECT_MODE_OUTPUT(reg, mask); // drive output low
interrupts();
delayMicroseconds(480); <<=== this is setting line low to 480us right?
noInterrupts();
DIRECT_MODE_INPUT(reg, mask); // allow it to float
delayMicroseconds(70); <==== 70us for presence ?
r = !DIRECT_READ(reg, mask);
interrupts();
delayMicroseconds(410);
return r;
}

#define DIRECT_READ(base, mask) ((((base)) & (mask)) ? 1 : 0) What does this mean ((((base)) & (mask)) ? 1 : 0)

"base" is a register pointer, so "*(base)" dereferences it (read the register), bitwise AND the contents of the register with "mask", and if the result is non-zero, return "1", otherwise return zero.

AWOL:

#define DIRECT_READ(base, mask) ((((base)) & (mask)) ? 1 : 0) What does this mean ((((base)) & (mask)) ? 1 : 0)

"base" is a register pointer, so "*(base)" dereferences it (read the register), bitwise AND the contents of the register with "mask", and if the result is non-zero, return "1", otherwise return zero.

Hi thanks again, I understand base being a register pointer. *(base) reads the register , it's bitwise AND'ed with mask . Can we apply a practical example here. This syntax ? 1 : 0 How does it work ? I see 1 : 0 . Why if result is non-zero ?.
Then DIRECT_READ I still don't understand where it's referenced on which header file. As to understand the internals. Sorry I'm so in depth but I'm looking forwards to make a UART implementation of one-wire and need to understand thoroughly how everything works. As there's no realtime debugging , stepping into or tracing a variable I have no wa to see in real time how everything works , rather than using a a serial.print to see how a variable behaves which it's really fuzzy and time consuming.

This syntax ? 1 : 0 How does it work ? I see 1 : 0 .

If the expression to the left of the "?" evaluates to "true" (non-zero) then return the value of the expression to the left of the colon, otherwise return the value of the expression to the right of the colon.

AWOL:

This syntax ? 1 : 0 How does it work ? I see 1 : 0 .

If the expression to the left of the "?" evaluates to "true" (non-zero) then return the value of the expression to the left of the colon, otherwise return the value of the expression to the right of the colon.

Thanks so this would mean

  • Read *base pointer.
  • Bit "AND" expression with mask.
  • So, ? 1: 0 it's basically an abbreviation to return either 1 or 0 if the expression is true or false?

Can you point me to some reference, where I can understand what these definitions mean. I've tried searching with google, but I get nothing with either DIRECT_READ + atmega 368, I even tried reading the whole datasheet to see if I could find anything.

On one if your posts you stated this :

The AVRs have three registers per I/O port - PORT, DDR, PIN at consecutive addresses.

, can you give me more insight on how these registers relate to the following definitions. DIRECT_READ, DIRECT_MODE_INPUT, DIRECT_MODE_OUTPUT, DIRECT_WRITE_LOW I understand the meaning but again can't find any reference. And it's useful for me to interpret how they work on onewire library.

#define DIRECT_READ(base, mask) ((((base)) & (mask)) ? 1 : 0)
#define DIRECT_MODE_INPUT(base, mask) ((
(base+1)) &= ~(mask))
#define DIRECT_MODE_OUTPUT(base, mask) (((base+1)) |= (mask))
#define DIRECT_WRITE_LOW(base, mask) ((
(base+2)) &= ~(mask))
#define DIRECT_WRITE_HIGH(base, mask) ((*(base+2)) |= (mask))

Thanks again.

#define DIRECT_READ(base, mask) (((*(base)) & (mask)) ? 1 : 0)
#define DIRECT_MODE_INPUT(base, mask) ((*(base+1)) &= ~(mask))
#define DIRECT_WRITE_LOW(base, mask) ((*(base+2)) &= ~(mask))

Consecutive addresses.
The names are nothing to do with Atmel or AVR, they're just something the author made up.

AWOL:

#define DIRECT_READ(base, mask) (((*(base)) & (mask)) ? 1 : 0)
#define DIRECT_MODE_INPUT(base, mask) ((*(base+1)) &= ~(mask))
#define DIRECT_WRITE_LOW(base, mask) ((*(base+2)) &= ~(mask))

Consecutive addresses.
The names are nothing to do with Atmel or AVR, they're just something the author made up.

Back again, I understand. Can you at least try to guide me , on how the following definitions (DIRECT_READ,DIRECT_MODE_INPUTDIRECT_WRITE_LOW), work below, taking into account digital pin 10 is being used to create an object instance.

OneWire::OneWire(uint8_t pin)
{
pinMode(pin, INPUT);
bitmask = PIN_TO_BITMASK(pin); <<<=== I know this brings up the bitmask corresponding to the arduino pin
for instance digital pin 13 brings 0b00100000. [/b]
baseReg = PIN_TO_BASEREG(pin); <<== I don't understand what this brings up to basereg

#if ONEWIRE_SEARCH
reset_search();
#endif
}
// Perform the onewire reset function. We will wait up to 250uS for
// the bus to come high, if it doesn't then it is broken or shorted
// and we return a 0;
//
// Returns 1 if a device asserted a presence pulse, 0 otherwise.
//

uint8_t OneWire::reset(void)
{
IO_REG_TYPE mask = bitmask; <<==bitmask if digital pin 13 is set here
IO_REG_TYPE is 0b00100000 ? right?

volatile IO_REG_TYPE *reg IO_REG_ASM = baseReg; <<== Lost here what does *reg mean
uint8_t r;
uint8_t retries = 125;
noInterrupts();
DIRECT_MODE_INPUT(reg, mask);
interrupts();

// wait until the wire is high... just in case
do {
if (--retries == 0) return 0;
delayMicroseconds(2);
} while ( !DIRECT_READ(reg, mask));

noInterrupts();
DIRECT_WRITE_LOW(reg, mask);
DIRECT_MODE_OUTPUT(reg, mask); // drive output low
interrupts();
delayMicroseconds(480); <<=== this is setting line low to 480us right?
noInterrupts();
DIRECT_MODE_INPUT(reg, mask); // allow it to float
delayMicroseconds(70); <==== 70us for presence ?
r = !DIRECT_READ(reg, mask);
interrupts();
delayMicroseconds(410);
return r;
}

I'm sorry, I really don't see how much clearer it could be - it does what the functions, macros and comments say it does.

AWOL:
I'm sorry, I really don't see how much clearer it could be - it does what the functions, macros and comments say it does.

kay ,thanks anyways. It's way cumbersome for me to understand without having a clear example using a value. And how the variables behave.
If you do you have some spare time.. and doesn't bother , see if you can provide me a nice example using the example I stated above defining an instance of the object on say D10
Once more thanks for your help.

@ AWOL +1

Doc

Docedison:
@ AWOL +1

Doc

what ?

It seems that your C knowledge is not quite up to the level needed to understand the code...

I'll take a try at clarifying, but I don't know how much it will help.

You do OneWire  ds(10);

   bitmask = PIN_TO_BITMASK(pin);  <<<=== I know this brings up the bitmask corresponding to the arduino pin
                                                                              for instance digital pin 13 brings   0b00100000.

Yes. For pin 10, bitmask will be 0b100;

   baseReg = PIN_TO_BASEREG(pin); <<== I don't understand what this brings up to basereg

This is roughly equivalent to the digital_pin_to_port_PGM[] function in pins_arduino.h, but instead of an arbitrary port, the code is setting baseReg to the first of the three IO registers associated with a port. In the case of pin 10, baseReg will be the address of PINB (0x23) That's also the input port, DDRB is 0x24 (baseReg+1), and PORTB is 0x25 (baseReg+2)
That means #define DIRECT_READ(base, mask)        (((*(base)) & (mask)) ? 1 : 0) is equivalent to digitalRead(); it reads from PINB (*(base)), masks with the bitmask (&), and adjusts to TRUE/FALSE values (?1:0)

#define DIRECT_MODE_INPUT(base, mask)   ((*(base+1)) &= ~(mask))

This clears the relevant bit in DDRB (*(base+1)), making the pin be an INPUT. It's equivalent to pinMode(pin, INPUT)

#define DIRECT_WRITE_LOW(base, mask)    ((*(base+2)) &= ~(mask))

This clears a bit in PORTB (*(base+2)), which writes LOW to the output pin. equivalent to digitalWrite(pin, 0);

DIRECT_MODE_OUTPUT and DIRECT_WRITE_HIGH work similarly. These are all just "convenient" macros for doing the equivalent of the arduino digitalRead/digitalWrite/pinMode functions, only MUCH faster because it doesn't do the conversion to port and bitmask EVERY TIME; just when you initialize the onewire object.

        volatile IO_REG_TYPE *reg IO_REG_ASM = baseReg;      <<== Lost here what does *reg mean

The whole statement means that 'reg' is a pointer of the appropriate type for an IO register (PINB), reg+1 will be DDRB, reg+2 will be PORTB. "*" is what makes it a pointer.

You need to understand C pointers to understand the inner workings of the arduino libraries.
You DON'T really need to understand pointers to fiddle with the onewire code. Just "trust" that the DIRECT_xxx macros do what their names say that they do...

DIRECT_READ == digitalRead(pin)
DIRECT_MODE_INPUT == pinMode(pin, INPUT)
DIRECT_MODE_OUTPUT == pinMode(pin, OUTPUT)
DIRECT_WRITE_LOW == digitalWrite(pin, LOW)
DIRECT_WRITE_HIGH == digitalWrite(pin, HIGH)

I wonder if it wouldn't be easier to understand what happens (without perhaps worrying too much about HOW it happens) by studying the Atmel datasheet for the Atmega328.

Asssuming the Arduino code works properly (and in general it all does) then it MUST translate the code into whatever is required by the 328 chip.

Then if you want to figure out HOW the Arduino code does its thing you can use your knowledge of what the chip requires (from the datasheet) to tackle the Arduino code from both ends.

...R

westfw:
It seems that your C knowledge is not quite up to the level needed to understand the code...

I'll take a try at clarifying, but I don't know how much it will help.

You do OneWire  ds(10);

   bitmask = PIN_TO_BITMASK(pin);  <<<=== I know this brings up the bitmask corresponding to the arduino pin

for instance digital pin 13 brings   0b00100000.



Yes. For pin 10, bitmask will be 0b100;



baseReg = PIN_TO_BASEREG(pin); <<== I don't understand what this brings up to basereg



This is roughly equivalent to the digital_pin_to_port_PGM[] function in pins_arduino.h, but instead of an arbitrary port, the code is setting baseReg to the first of the three IO registers associated with a port. In the case of pin 10, baseReg will be the address of PINB (0x23) That's also the input port, DDRB is 0x24 (baseReg+1), and PORTB is 0x25 (baseReg+2)
That means `#define DIRECT_READ(base, mask)         (((*(base)) & (mask)) ? 1 : 0)` is equivalent to digitalRead(); it reads from PINB (*(base)), masks with the bitmask (&), and adjusts to TRUE/FALSE values (?1:0)


#define DIRECT_MODE_INPUT(base, mask)   ((*(base+1)) &= ~(mask))



This clears the relevant bit in DDRB (*(base+1)), making the pin be an INPUT. It's equivalent to pinMode(pin, INPUT)



#define DIRECT_WRITE_LOW(base, mask)    ((*(base+2)) &= ~(mask))



This clears a bit in PORTB (*(base+2)), which writes LOW to the output pin. equivalent to digitalWrite(pin, 0);

DIRECT_MODE_OUTPUT and DIRECT_WRITE_HIGH work similarly. These are all just "convenient" macros for doing the equivalent of the arduino digitalRead/digitalWrite/pinMode functions, only MUCH faster because it doesn't do the conversion to port and bitmask EVERY TIME; just when you initialize the onewire object.



volatile IO_REG_TYPE *reg IO_REG_ASM = baseReg;      <<== Lost here what does *reg mean



The whole statement means that 'reg' is a pointer of the appropriate type for an IO register (PINB), reg+1 will be DDRB, reg+2 will be PORTB. "*" is what makes it a pointer. 

You need to understand C pointers to understand the inner workings of the arduino libraries.
You DON'T really need to understand pointers to fiddle with the onewire code. Just "trust" that the DIRECT_xxx macros do what their names say that they do...

DIRECT_READ == digitalRead(pin)
DIRECT_MODE_INPUT == pinMode(pin, INPUT)
DIRECT_MODE_OUTPUT == pinMode(pin, OUTPUT)
DIRECT_WRITE_LOW == digitalWrite(pin, LOW)
DIRECT_WRITE_HIGH == digitalWrite(pin, HIGH)

Sorry for the late reply I had some things to do. Superb explanation, I was looking for someone to contribute with this explanation. I'm going to review step by step your explanation. And I think you're right. I think I need a good resource dealing with pointers to fully understand how this onewire protocol implementation works. Can you recommend me a good pointer resource , I know I can google around. But this has to do specifically with pointers and registers to fully understand in this case a onewire protocol implementation done by someone else.
To be entirely honest, it would be easier for me if I could have an IDE were I could step into the values of variables.But this is not possible with the arduino ide. So I'm left up to manually see which values are assigned to the different values.
Again I gladly apreciatte your effort towards explaining to me. I was looking for someone to go into the code the way you did. But it would be an added bonus if you we could still go through it with the pin number example I stated before. Say we're using digital pin 10 which value each of the registers will have assigned in binary, when they are bitwise AND'ed and so on.
But again.. I think It would be a good idea if you can guide me onto a good pointer reference but pinpointed specifically towards this kind of implementations, as there are typical c++ tutorials dealing with pointers but quite generic.