I am trying to use an Arduino Uno as part of a larger circuit that synchronizes two square voltage waveforms (those waveforms are fed into pins of the Uno). The Uno will be activated by a digital signal from another part of the larger circuit, and that activation signal will be sustained for a few seconds at a time. While the activation signal is HIGH, the Uno's job will just be to detect when its measured square waveforms are synchronized: it will monitor them and generate a pulse of its own if they reach their zero crossings within about 100 microseconds of each other (the square waves themselves are ~50Hz).
Because 100us is a pretty short window, I thought I'd try direct bit manipulation rather than using DigitalRead() or DigitalWrite(). This is my first time trying bit manipulation, though, and my C experience is pretty limited in general. I have the first draft of my code here - if any of you can tell me whether the logic of it seems sound, I would very much appreciate it!
It looks long, but there are only a few lines' worth of ideas, the rest is a bunch of copy/pasted blocks (which no doubt means there are much more elegant ways to write it).
// Synchronism detector
// This code is built to run on an Arduino Uno.
// The hardware timer runs at 16MHz. Using a
// divide by 8 on the counter each count is
// 500 ns and a 50Hz wave cycle is 40000 clock cycles.
#include <avr/io.h>
#include <avr/interrupt.h>
void setup(){
// Set clock prescaler
// This is set to 'divide by 8' but if I can get away
// with using delay statements that doesn't really matter
TCCR1B &= ~(1 << CS12);
TCCR1B != ~(1 << CS11);
TCCR1B &= ~(1 << CS10);
// Set up pins
// 3rd bit of port D will be the activation flag
// 4th and 5th bits will be read pins for the incoming waves
DDRD = DDRD & B11100011
// Note that I'll also have the incoming waves going into the int0 and int1 pins
// 6th bit will be a write pin for the outgoing signal
DDRD = DDRD | B00100000
PORTD = PORTD & B11011111
// Set initial values for zero-cross detect flags
wave_0 = ((PIND & B00001000) >> 3);
wave_0_prev = ((PIND & B00001000) >> 3);
wave_1 = ((PIND & B00010000) >> 4);
wave_1_prev = ((PIND & B00010000) >> 4);
}
void loop(){
// Poll activation flag
if (((PIND & B00000100) >> 2) == 1)
// Poll wave input pins
wave_0 = ((PIND & B00001000) >> 3);
wave_1 = ((PIND & B00010000) >> 4);
// Check zero crossing detection,
// Start with wave 0, rising edge
if (wave_0 == 1 && wave_0_prev == 0))
attachInterrupt(int1,sync_interrupt, RISING);
delay(.0001);
detachInterrupt(int1);
// Reset pins
wave_0 = ((PIND & B00001000) >> 3);
wave_0_prev = ((PIND & B00001000) >> 3);
wave_1 = ((PIND & B00010000) >> 4);
wave_1_prev = ((PIND & B00010000) >> 4);
)
// Wave 0, falling edge
if (wave_0 == 0 && wave_0_prev == 1))
attachInterrupt(int1,sync_interrupt, FALLING);
delay(.0001);
detachInterrupt(int1);
// Reset pins
wave_0 = ((PIND & B00001000) >> 3);
wave_0_prev = ((PIND & B00001000) >> 3);
wave_1 = ((PIND & B00010000) >> 4);
wave_1_prev = ((PIND & B00010000) >> 4);
)
// Wave 1, rising edge
if (wave_1 == 1 && wave_1_prev == 0))
attachInterrupt(int0,sync_interrupt, RISING);
delay(.0001);
detachInterrupt(int0);
// Reset pins
wave_0 = ((PIND & B00001000) >> 3);
wave_0_prev = ((PIND & B00001000) >> 3);
wave_1 = ((PIND & B00010000) >> 4);
wave_1_prev = ((PIND & B00010000) >> 4);
)
// Wave 1, falling edge
if (wave_1 == 0 && wave_1_prev == 1))
attachInterrupt(int0,sync_interrupt, FALLING);
delay(.0001);
detachInterrupt(int0);
// Reset pins
wave_0 = ((PIND & B00001000) >> 3);
wave_0_prev = ((PIND & B00001000) >> 3);
wave_1 = ((PIND & B00010000) >> 4);
wave_1_prev = ((PIND & B00010000) >> 4);
)
}
sync_interrupt(){
// Set output bit high
PORTD = PORTD | B00100000
delay(.001}
// Set output bit low
PORTD = PORTD & B00100000
// Reset pins
wave_0 = ((PIND & B00001000) >> 3);
wave_0_prev = ((PIND & B00001000) >> 3);
wave_1 = ((PIND & B00010000) >> 4);
wave_1_prev = ((PIND & B00010000) >> 4);
}
Thanks again for any help.
OK, so I'm not too sure what exactly the interrupt flags are for this particular device, however personally I would say the easiest way to go about this is to have it such that you have 2 interrupts set up for each of the inputs and to have each of the interrupts blocks of code set up to activate the timer interrupt as well via a jump from an output pin. This way when one is activated if the other one is not activated within the timed period you can reset the interrupt flags, and if the second one is activated then you can run the code you wish to run when the waves are synchronised
Related
I'm using I2C register to config for device driver but:
I cannot read/write I2C register after request_mem_region() -> ioremap(). I see that just happens with I2C, UART, SPI... but I still can use with GPIO and TIMER.
I tried to change config in menuconfig before building distro but it's efficient (enable Embedded system, enable map Ram...). Of course, I too tried readl(), writel(), iowrite32(), ioread32()...
But code works fine when I edit I2C register that is available when configuring the distro and can see it on /dev/iomem.
I think there is a problem with ram access. But how to fix it? Thanks!
After code for test:
u8 twi_mem_flag = 0;
int PIOA_Init(void)
{
if (!request_mem_region(TWI_BASE, 0x400, "TWI_MEM")) {
printk(KERN_INFO "TWI_MEM is existed\n");
twi_mem_flag = 1;
}
PA_CFG0_REG = (uint32_t *) ioremap(PA_CFG0, 4);
PA_PUL0_REG = (uint32_t *) ioremap(PA_PUL0, 4);
PA_DATA_REG = (uint32_t *) ioremap(PA_DAT, 4);
PA_DRV0_REG = (uint32_t *) ioremap(PA_DRV0, 4);
PA_EINT_CFG0_REG = (uint32_t *) ioremap(PA_EINT_CFG0, 4);
PA_EINT_CTL_REG = (uint32_t *) ioremap(PA_EINT_CTL, 4);
PA_EINT_STATUS_REG = (uint32_t *) ioremap(PA_EINT_STATUS, 4);
PA_EINT_DEB_REG = (uint32_t *) ioremap(PA_EINT_DEB, 4);
TWI_ADDR_REG = (uint32_t *) ioremap(TWI_ADDR, 4);
TWI_XADDR_REG = (uint32_t *) ioremap(TWI_XADDR, 4);
TWI_DATA_REG = (uint32_t *) ioremap(TWI_DATA, 4);
TWI_CNTR_REG = (uint32_t *) ioremap(TWI_CNTR, 4);
*PA_CFG0_REG &= ~(0X77 << 24);
*PA_CFG0_REG |= (0X01 << 24);
*PA_PUL0_REG &= ~(0X0f << 12);
*PA_PUL0_REG |= (0X05 << 12);
*PA_EINT_CFG0_REG = (0x03 << 28);
*PA_EINT_CTL_REG = (0x01 << 7);
*PA_EINT_STATUS_REG = (0x01 << 7);
*PA_EINT_DEB_REG = (0x11);
*TWI_ADDR_REG |= 0x07;
*TWI_DATA_REG |= 0x77;
*TWI_CNTR_REG |= 0x05;
printk( KERN_INFO "GPIO: %x - %x - %x - %x\n", *PA_CFG0_REG, *PA_PUL0_REG, *PA_DATA_REG, *PA_DRV0_REG);
printk( KERN_INFO "TWI: %x - %x - %x - %x\n", *TWI_ADDR_REG, *TWI_XADDR_REG, *TWI_DATA_REG, *TWI_CNTR_REG);
return 0;
}
void PIOA_destroy(void)
{
iounmap(PA_DRV0_REG);
iounmap(PA_DATA_REG);
iounmap(PA_CFG0_REG);
iounmap(PA_PUL0_REG);
iounmap(PA_EINT_CFG0_REG);
iounmap(PA_EINT_CTL_REG);
iounmap(PA_EINT_STATUS_REG);
iounmap(PA_EINT_DEB_REG);
iounmap(TWI_ADDR_REG);
iounmap(TWI_XADDR_REG);
iounmap(TWI_DATA_REG);
iounmap(TWI_CNTR_REG);
if (!twi_mem_flag)
release_mem_region(TWI_BASE, 0x400);
}
[ 228.246399] GPIO: 1227777 - 5400 - 0 - 55555555
[ 228.246420] TWI: 0 - 0 - 0 - 0
[ 228.246428] The blink led device is installed !!
An external interrupt vector should occur when a 5v input is supplied to int0.
The interrupt should change a volatile integer flag to allow a LED to illuminate that is connected to a pin on PORTB. Compiles with no errors in Atmel studio. The problem is no change occurs when a 5v supply is sent to the int0 pin. Is this that the interrupt is not triggering?
#include <avr/io.h>
#include <stdio.h>
#define F_CPU 16000000UL
#include <util/delay.h>
#include <avr/interrupt.h>
volatile int pwm_flag=0;
int main(void)
{
DDRD &= ~(1 << DDD2); // Clear the PD2 pin
// PD2 (PCINT0 pin) is now an input
PORTD |= (1 << PORTD2); // turn On the Pull-up
// PD2 is now an input with pull-up enabled
EICRA |= (1 << ISC00)|(1 << ISC10); // set INT0 to trigger on Rising edge
EIMSK |= (1 << INT0); // Turns on INT0
sei(); // turn on interrupts
DDRB = 0xFF;
PORTB = 0x00;
while(1)
{
if(pwm_flag==1)//if flag is raised
{
PORTB = 0xFF;//turn on all pins of portb
pwm_flag=0;//reset flag to 0
}
}
}
ISR (INT0_vect)
{
/* interrupt code here */
pwm_flag =1;//raise flag
}
The problem is no change occurs when a 5v supply is sent to the int0 pin.
How do you send 5V to the INT0 pin? Your code is setting INT0 pin as an input with pullup so unless you short it to the ground it is at 5V.
Also, what do you mean by no change occurs? Is the LED on or off?
Another thing is that the line:
EICRA |= (1 << ISC00)|(1 << ISC10);
sets both INT0 and INT1 to occur on any logical change on appropriate pin. Bits with name ISC0x control INT0, bits called ISC1x are used to configure INT1. In your code you are mixing both and you end up with the following configuration:
ISC01 | ISC00 | meaning
-------------------------------------------------------------------------
0 | 1 | any logical change on INT0 generates an interrupt request
ISC11 | ISC10 | meaning
-------------------------------------------------------------------------
0 | 1 | any logical change on INT1 generates an interrupt request
If you are trying to supply 5v from a pin on PORTB to an LED then perhaps that is your problem. Most micro-controller pins can sink more current than they can give. Perhaps your LED is just not getting the current it needs?
Your wiring should be as follows:
Connect the positive leg of the LED to 5V. Connect the negative leg to a small resistor 100-500 Ohms. Connect the other leg of the resistor to the pin on PORTB.
Now you can write PORTB to 0x00 to turn on the LED or 0xFF to turn it off.
To test that the LED is working test the LED in your main loop by writing PORTB low and high with a noticeable delay in between.
If that works. Then test your ISR. If the ISR doesn't work a this point then the ISR is the problem.
Bear in mind that in your current configuration of EICRA you are triggering an interrupt on a rising edge. So if the pin is already high not interrupt will occur.
I have changed your code below so LOW is ON and HIGH is OFF.
int main(void){
DDRD &= ~(1 << DDD2); // set PD2 DDR as input
PORTD |= (1 << PORTD2); // set PD2 as input pull-up
EICRA |= (1 << ISC00)|(1 << ISC10); // set INT0 to trigger on rising edge
EIMSK |= (1 << INT0); // Turns on INT0
DDRB = 0xFF; // set PORTB as all outputs
PORTB = 0xFF; // set PORTB high
sei(); // turn on interrupts
while(1){
if(pwm_flag!=0){ // check flag
PORTB = 0x00; // set PORTB low
pwm_flag=0; // reset flag
}
}
ISR (INT0_vect){
pwm_flag = 1; // raise flag
}
i am trying to Read an Voltage Level via a ADC0 of my ATmega8, because of querying a 1 Pin 4x4 Matrix Keypad. The Problem is everytime I apply a Voltage to the ADC higher than GND the Atmega is stopping to do his work. The PWM outputs are still working, but communication via i2c is impossible and the LCD is clear.
My wiring is simple, AREF & AVCC are set to 5V, GND is set to GND and PC0 is my Input. Is there anything I fail to Notice? Thank You for your help.
Here is my Code:
void Initialisierung(void)
{
char text [2];
lcd_init();
cli();
//### TWI
init_twi_slave(SLAVE_ADRESSE); //TWI als Slave mit Adresse slaveadr starten
sei();
lcd_setcursor( 0, 1 );
lcd_string(">Booting...");
lcd_setcursor( 0, 2 );
itoa (SLAVE_ADRESSE,text,16);
lcd_string("I2C Adress=0x");
lcd_string(text);
for (int Index=0; Index<85; ++Index) {
rxbuffer[Index] = 0x20;
}
rxbuffer[81]=0xFF;
rxbuffer[82]=0xFF;
rxbuffer[83]=0xFF;
rxbuffer[84]=0xFF;
}
//update LCD
void lcd_update(void){
for (int o=1;o<=4; o++)
for (int i=1; i<=20; i++){
lcd_setcursor( i-1, o );
lcd_data(rxbuffer[i+((o-1)*20)]);
}
}
An here is the main function:
int main(void)
{
DDRC &= ~(1 << PC0);
PORTC &= ~(1 << PC0);
Initialisierung();
DDRB = (1 << DDB1) | (1 << DDB2);
OCR1A = eeprom_read_word(&brightness); // PWM einstellen,
OCR1B = eeprom_read_word(&contrast);
ICR1 = 1000; // TOP-wert
TCCR1A = (1<<COM1A1) | (1<<COM1B1) | (1<<WGM11); // 2-Kanal "non-inverting"
TCCR1B = (1<<WGM13)|(1<<WGM12) | (1<<CS11);
//Initialize ADC
ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS0);
ADMUX=0x00;
unsigned int adc_value=0; // Variable to hold ADC result
char text[2];
while(1)
{
ADCSRA |= (1<<ADSC); // Start conversion
while (ADCSRA & (1<<ADSC)); // wait for conversion to complete
adc_value = ADCW; //Store ADC value
itoa (adc_value,text,16);
lcd_setcursor( 0,4 );
lcd_string(text);
for (int Index=0; Index<85; ++Index) {
txbuffer[Index] = rxbuffer[Index];
}
uint16_t brightness_i2c=0;
uint16_t contrast_i2c=0;
brightness_i2c=(rxbuffer[81]<<8)|(rxbuffer[82]);
contrast_i2c=(rxbuffer[83]<<8)|(rxbuffer[84]);
if (rxbuffer[0]==1){
lcd_update();
rxbuffer[0]=4;
}else if(brightness_i2c!=eeprom_read_word(&brightness) && brightness_i2c!=0xFFFF){
eeprom_write_word(&brightness,brightness_i2c);
OCR1A = eeprom_read_word(&brightness);
}else if (contrast_i2c!=eeprom_read_word(&contrast) && contrast_i2c!=0xFFFF){
eeprom_write_word(&contrast,contrast_i2c);
OCR1B = eeprom_read_word(&contrast);
}else{
for (uint8_t i=0; i<50; i++) _delay_ms(10);
lcd_setcursor( 19, 4 );
lcd_data(0xFF);
for (uint8_t i=0; i<50; i++) _delay_ms(10);
lcd_setcursor( 19, 4 );
lcd_data(0x20);
}
}
}
I finally got it:
I setup the ADC with interrupts but not freerunning:
ADCSRA =(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADIE)| (1<<ADPS0);
And call the ADC everytime at the end of my While loop:
ADCSRA |= (1<<ADSC);
Here is the Code for the ISR:
ISR(ADC_vect)
{
char text[5];
itoa (ADC,text,16);
lcd_setcursor( 0,4 );
lcd_string(text);
}
Thanks for your time ;)
I need to implement as fast as possible left bit shift of a 16-byte array in JavaCard.
I tried this code:
private static final void rotateLeft(final byte[] output, final byte[] input) {
short carry = 0;
short i = (short) 16;
do {
--i;
carry = (short)((input[i] << 1) | carry);
output[i] = (byte)carry;
carry = (short)((carry >> 8) & 1);
} while (i > 0);
}
Any ideas how to improve the performace? I was thinking about some Util.getShort(...) and Util.setShort(...) magic, but I did not manage to make it work faster then the implementation above.
This is one part of CMAC subkeys computation and it is done quite often, unfortunately. In case you know some faster way to compute CMAC subkeys (both subkeys in one loop or something like that), please, let me know.
When it comes for speed, known length, hard-coded version is the fastest (but ugly). If you need to shift more than one bit, ensure to update the code accordingly.
output[0] = (byte)((byte)(input[0] << 1) | (byte)((input[1] >> 7) & 1));
output[1] = (byte)((byte)(input[1] << 1) | (byte)((input[2] >> 7) & 1));
output[2] = (byte)((byte)(input[2] << 1) | (byte)((input[3] >> 7) & 1));
output[3] = (byte)((byte)(input[3] << 1) | (byte)((input[4] >> 7) & 1));
output[4] = (byte)((byte)(input[4] << 1) | (byte)((input[5] >> 7) & 1));
output[5] = (byte)((byte)(input[5] << 1) | (byte)((input[6] >> 7) & 1));
output[6] = (byte)((byte)(input[6] << 1) | (byte)((input[7] >> 7) & 1));
output[7] = (byte)((byte)(input[7] << 1) | (byte)((input[8] >> 7) & 1));
output[8] = (byte)((byte)(input[8] << 1) | (byte)((input[9] >> 7) & 1));
output[9] = (byte)((byte)(input[9] << 1) | (byte)((input[10] >> 7) & 1));
output[10] = (byte)((byte)(input[10] << 1) | (byte)((input[11] >> 7) & 1));
output[11] = (byte)((byte)(input[11] << 1) | (byte)((input[12] >> 7) & 1));
output[12] = (byte)((byte)(input[12] << 1) | (byte)((input[13] >> 7) & 1));
output[13] = (byte)((byte)(input[13] << 1) | (byte)((input[14] >> 7) & 1));
output[14] = (byte)((byte)(input[14] << 1) | (byte)((input[15] >> 7) & 1));
output[15] = (byte)(input[15] << 1);
And use RAM byte array!
This is the fastest algorithm to rotate arbitrary number of bits I could come up with (I rotate array of 8 bytes, you can easily transform it to shifting 16 instead):
Use EEPROM to create a masking table for your shifts. Mask is just increasing amounts of 1s from the right:
final static byte[] ROTL_MASK = {
(byte) 0x00, //shift 0: 00000000 //this one is never used, we don't do shift 0.
(byte) 0x01, //shift 1: 00000001
(byte) 0x03, //shift 2: 00000011
(byte) 0x07, //shift 3: 00000111
(byte) 0x0F, //shift 4: 00001111
(byte) 0x1F, //shift 5: 00011111
(byte) 0x3F, //shift 6: 00111111
(byte) 0x7F //shift 7: 01111111
};
Then you first use Util.arrayCopyNonAtomic for quick swap of bytes if shift is larger than 8:
final static byte BITS = 8;
//swap whole bytes:
Util.arrayCopyNonAtomic(in, (short) (shift/BITS), out, (short) 0, (short) (8-(shift/BITS)));
Util.arrayCopyNonAtomic(in, (short) 0, out, (short) (8-(shift/BITS)), (short) (shift/BITS));
shift %= BITS; //now we need to shift only up to 8 remaining bits
if (shift > 0) {
//apply masks
byte mask = ROTL_MASK[shift];
byte comp = (byte) (8 - shift);
//rotate using masks
out[8] = in[0]; // out[8] is any auxiliary variable, careful with bounds!
out[0] = (byte)((byte)(in[0] << shift) | (byte)((in[1] >> comp) & mask));
out[1] = (byte)((byte)(in[1] << shift) | (byte)((in[2] >> comp) & mask));
out[2] = (byte)((byte)(in[2] << shift) | (byte)((in[3] >> comp) & mask));
out[3] = (byte)((byte)(in[3] << shift) | (byte)((in[4] >> comp) & mask));
out[4] = (byte)((byte)(in[4] << shift) | (byte)((in[5] >> comp) & mask));
out[5] = (byte)((byte)(in[5] << shift) | (byte)((in[6] >> comp) & mask));
out[6] = (byte)((byte)(in[6] << shift) | (byte)((in[7] >> comp) & mask));
out[7] = (byte)((byte)(in[7] << shift) | (byte)((in[8] >> comp) & mask));
}
You can additionally remove mask variable and use direct reference to the table instead.
Using this rather than naive implementation of bit-wise rotation proved to be about 450% - 500% faster.
It might help to cache CMAC subkeys when signing repeatedly using the same key (i.e. the same DESFire EV1 session key). The subkeys are always the same for the given key.
I think David's answer could be even faster if it used two local variables to cache the values read twice from the same offset of the input array (from my observations on JCOP, the array access is quite expensive even for transient arrays).
EDIT: I can provide the following implementation which does 4 bit right shift using short (32-bit int variant for cards supporting it would be even faster):
short pom=0; // X000 to be stored next
short pom2; // loaded value
short pom3; // 0XXX to be stored next
short curOffset=PARAMS_TRACK2_OFFSET;
while(curOffset<16) {
pom2=Util.getShort(mem_PARAMS, curOffset);
pom3=(short)(pom2>>>4);
curOffset=Util.setShort(mem_RAM, curOffset, (short)(pom|pom3));
pom=(short)(pom2<<12);
}
Beware, this code assumes same offsets in source and destination.
You can unroll this loop and use constant parameters if desired.
I am fairly new to programming microcontrollers. I have some experience with the Arduino, but after I had nearly finished my project, I deceided to moved my current project to something cheaper and smaller. So I am now using the AVR ATmega32 with Atmel studio.
I'm trying to use the ATmega32 to communicate to a MAX7219 chip for multiplexing with an led matrix. however, I do have multiple different devices that I want to communicate with.
How can I communicate with the device without actually using the SPI pins provided on the microcontroller? I have made a test project, but there seems to be something wrong and I can't figure it out what the issue is. I think I managed to get it in test mode, because all LEDs are lit, but I can't get it to do anything after that. I can't even clear the display/shut it down. I have checked the wiring over again. Is my coding perhaps incorrect as far as pin configuration and assigning the pins? Are there any suggestions for this or a better way to write my code?
Here is the link to the MA7219 datasheet
//test
#include <avr/io.h>
int main(void)
{
DDRB = 0b00000111; // pin 1(data), 2(clock) and 3(latch) are outputs
PORTB = 0 << PINB0; // data pin 1 is low
PORTB = 0 << PINB1; // clock pin 2 is low
PORTB = 0 << PINB2; // latch pin 3 is low
uint16_t data;
data = 0b0000110000000000; // data to shift out to the max7219
//read bit
uint16_t mask;
for (mask = 0b0000000000000001; mask>0; mask <<= 1)
{
//iterate through bit mask
if (data & mask)
{ // if bitwise AND resolves to true
// send one
PORTB = 1 << PINB0;
// tick
PORTB = 1 << PINB1;
// tock
PORTB = 0 << PINB1;
}
else{ //if bitwise and resolves to false
// send 0
// send one
PORTB = 0 << PINB0;
// tick
PORTB = 1 << PINB1;
// tock
PORTB = 0 << PINB1;
}
}
PORTB = 1 << PINB2; // latch all the data
PORTB = 1 << PINB0; // data pin 1 is high
PORTB = 0 << PINB1; // clock pin 2 is low
PORTB = 0 << PINB2; // latch pin 3 is low
}
Yes, your bit-bang code has a problem in that you assign the entire value of the register each time without preserving the existing value. Hence you erase your data signal at the instant you drive your clock, violating the hold time of the receiver and resulting in unpredictable operation.
Instead of assigning pins with =, you should set them with |= or clear them with &= ~(value)
For example:
PORTB = 1 << PINB0; //drive data
// tick
PORTB |= 1 << PINB1; //clock high PRESERVING data
// tock
PORTB &= ~(1 << PINB1); //clock low
You may also need to insert a slight delay between pin operations.
Technically, given that you are already using an if for the data state, you could also re-drive the data signal with an OR in the assignment, for example
if (data & mask)
{ // if bitwise AND resolves to true
// send one
PORTB = 1 << PINB0;
// tick
PORTB = (1 << PINB1) | (1 << PINB0);
// tock
PORTB = 0 << PINB1 | (1 << PINB0);
}
else{ //if bitwise and resolves to false
// send 0
// send one
PORTB = 0 << PINB0;
// tick
PORTB = 1 << PINB1;
// tock
PORTB = 0 << PINB1;
}