Instrucción a nivel PUERTO

Buen día.

Soy un principiante utilizando Arduino. Estoy intentado programarlo a nivel de registros.
He encontrado algunos ejemplos en internet pero hay cosas que no me quedan claras.

Mi primer código es para apagar y prender un led pulsando un botón. Es el siguiente:

void setup()
{
 DDRB = 0x01;          //Configuración del puerto B. P1 como salida. 
}

void loop()
{
   if(PINB & (1<<PB1)) /*Compara si el botón está presionado */
   {
     PORTB = (1<<PB0); //Enciende el led
   }
   else
   {
     PORTB = (0<<PB0); //Apaga el led
   }
}

Entiendo muy bien cómo funcionan los registros PORT, PIN y DDR, de hecho el código hace su propósito. Sin embargo, la parte que no me queda totalmente clara es la condición:

  if(PINB & (1<<PB1))

Por lo que entiendo, con PINB se lee todo lo que esté en el puerto. Pero no entiendo qué es y cómo funciona (1<<PB1). No comprendo cómo es que hace una operacion AND entre un registro PINB y un bit PB1 y determinar cuando la condición es true o cuando es false.

Espero que me puedan resolver esta duda.

Saludos.

Woow pues para estar empezando te fuiste a la manera más enrevesada, a bajo nivel :o
A mí me gusta comprimir código pero a esos niveles suele darme pereza para leer cuando son muchas líneas. Eso sí, es más rápido, así que si le das a empeño a esto, felicidades :art: :sunglasses: Comenta cada línea para evitar dolores de cabeza tras un tiempo sin ver el ejercicio :grin:

Supongo que la duda es lo que hace el operador << y entender el bit que se evalúa.

Pienso que aquí se puede entender bien con los ejemplos lo que hace el operador <<:
https://www.arduino.cc/en/Reference/Bitshift

No obstante nada hago repitiendo los ejemplos que ya está en internet:

Edito: Saludos y ánimo con esa fortaleza de empezar con el bajo nivel… pero en este foro no hallarás tantos ejemplos (en la parte de inglés mejor)

Entiéndelo si pones esto para encender un led puedes matar las neuronas de alguien, a las mías sin ir más lejos les da sueño :grin: :grin: :grin:

void setup(){
  DDRB = 0x01;
}
void loop(){
  PORTB = (PINB & (1<<PB1)) ? (1<<PB0) : (0<<PB0);
}

Por cierto ya que vas a usar bajo nivel ¿No te viene mejor usar binario y hacer las entradas/salidas del tirón?

En plan:

DDRD= B11111100;

y encender al estilo:

PORTD= B11111100;

Vale que a lo mejor no quieras encender todos esos leds, pero a mí binario me parece más legible y el ahorro de líneas para definir entradas y salidas es genial.