1
votes

I am trying to understand this code

But I am having trouble understanding this part of the code.

#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= -_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

sbi and cbi are later being used in the code as

void system_sleep()
{
  sbi(MCUCR,PUD);                                  //Disables All Internal Pullup Resistors
  sbi(GIMSK,PCIE);                                   //Enable Pin Change Interrupts Interrups
  sbi(PCMSK,PCINT0);                              //Changes Interrupt to PIN1 (PCINT1) 
  cbi(ADCSRA,ADEN);                              //switch Analog to Digital Converter OFF
  cbi(MCUCR,SM0);                                  //Power Down Mode
  sbi(MCUCR,SM1);                                  //Power Down Mode
  sbi(MCUCR,SE);   //sleep Mode Power down enable (Sleep_enable(); should set this-- not tested yet)
  sleep_enable();                      //Sets the Sleep Enable bit in the MCUCR Register (SE BIT)
  sleep_mode();                                       //sleep begins here
  sleep_disable();                                     //Coming out of sleep
  sbi(ADCSRA,ADEN);                             //switch Analog to Digital Converter ON
  cbi(MCUCR,PUD); //Enables Pullup Resistors Again 
 }

The code is for ATtiny85 and I read the data sheet and I came to know that all these like MCCUR and ADCSRA etc are all registers. Also it states that there are two kinds of instructions SBI and CBI.

I also read some tutorials about micro controller programming using C and understand that each register has 8 bits. Each of these bits can be set using programming for different functionality. Also PUD, PCIE are different bits of these registers and these are being set in the system_sleep function. So I understand what system_sleep function is doing , it is setting the bits in the register.

The only part I am not able to understand is

#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= -_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

There is nothing in the data sheet like _SFR_BYTE or _BV. I looked into AVR/libc headers, there I found _BV but not sure what is it doing.

3

3 Answers

3
votes

The names of the macros should give you some hint. cbi stands for Clear Bit and sbi stands for Set Bit. cbi(sfr, bit) clears bit-number indicated by bit in the register sfr. Similar explanation for sbi.

If you have the whole project, you can search for the definition of _SFR_BYTE and _BV. But in essense they roughly translate into

#define  cbi(sfr, bit)   ((sfr) &= ~(1 << (bit)))

#define  sbi(sfr, bit)   ((sfr) |= (1 << (bit)))

Read more about bit-masking.

1
votes
#define _BV(bit)       (1 << (bit))
#define _SFR_BYTE(sfr) _MMIO_BYTE(_SFR_ADDR(sfr))

The first one _BV, as an example, instead of writing 1<<0 in your code you can write just _BV(0). The second one _SFR_BYTE uses the _MMIO_BYTE macro to get the data from the register sfr which could be MCUCR or ADCSRA or any 8bit IO register.

For more information refer to avr/sfr_defs.h

0
votes

The AVR ATMega registers from 0x00 to 0x1F may be read / written using the in and out instructions, moreover specific instructions that works on these registers there're . These registers may be also read using memory instructions. In this case those register addresses must take the values from 0x20 to 0x3F.

The macros __SFR_xxxx take in account this behavior.

These are quotes of the notes of the paragraph "Register Summary" of the ATMega 2560:

-2. I/O registers within the address range $00 - $1F are directly bit-accessible using the SBI and CBI instructions. In these reg- isters, the value of single bits can be checked by using the SBIS and SBIC instructions.

-4. When using the I/O specific commands IN and OUT, the I/O addresses $00 - $3F must be used. When addressing I/O regis- ters as data space using LD and ST instructions, $20 must be added to these addresses. The ATmega640/1280/1281/2560/2561 is a complex microcontroller with more peripheral units than can be supported within the 64 location reserved in Opcode for the IN and OUT instructions. For the Extended I/O space from $60 - $1FF in SRAM, only the ST/STS/STD and LD/LDS/LDD instructions can be used.