Assignment 
  • Group Assignment:
    • compare the performance and development workflows
      for other architectures
  • Individual Assignment:
    • Read a microcontroller data sheet
    • program your board to do something,
      with as many different programming languages
      and programming environments as possible
Evaluation Standards 
  • Link to the group assignment page
  • Document what I learned from reading a microcontroller datasheet
  • Program my board
  • Describe the programming process/es I used
  • Include my source code
  • Include a short ‘hero video’ of my board
Output Preview  


Arduino-C AVR-C iArduino




 Group Assignment

A microcontroller (MCU) is a compact integrated circuit designed to do a specific operation in an embedded system. A typical microcontroller includes a processor, memory and input/output (I/O) peripherals on a single chip.

MCUs are useless to be used alone. They require to be integrated within as system on sensors, actuators, programmers, power regulation, and more.

A single-board microcontroller is a microcontroller built onto a single printed circuit board. This board provides all of the circuitry necessary for a useful control task: a microprocessor, I/O circuits, a clock generator, RAM, stored program memory and any necessary support ICs. The intention is that the board is immediately useful to an application developer, without requiring them to spend time and effort to develop controller hardware.

I have many MCU boards and I decided to benchmark the core processors of each board.

Arduino Software (IDE) have all Arduino AVR boards installed by default. Some other boards can be programmed from the IDE but they require additional software core to be installed. Cores are necessary to make new microcontrollers compatible with your Arduino Software (IDE) and, possibly, the existing sketches and libraries.

In order to program the Node MCU and Arduino 101; I've Installed the following cores:

I then uploaded to following speed test code on each board and opened the serial port to get the following benchmark data.

                                    
// Arduino Speed Test Benchmarking Program
// Original Program Credit: Arduino.cc
// Modified By: Dan Watson
// synchannel.blogspot.com
// 1-29-2015

void setup()
{
  Serial.begin(9600);
  
  pinMode(9, OUTPUT);
  pinMode(10, INPUT);
  
  Serial.println("Speed Test will begin momentarily.");
  Serial.println("");
 
 delay(4000);
  
  speedTest();
}

void loop()
{
  // Do nothing
}

void speedTest(void)
{
  register int i,j;
  volatile unsigned char c1,c2;
  volatile int v;
  volatile long l1,l2;
  volatile float f1,f2;
  int p,q;
  long int r;
  unsigned long m,n;
  float d, overhead;
  char buffer[30];

  Serial.println(F(""));
  Serial.println(F("Speed test"));
  Serial.println(F("----------"));

  Serial.print(F("F_CPU = "));
  Serial.print(F_CPU,DEC);
  Serial.println(F(" Hz"));
  Serial.print(F("1/F_CPU = "));
  Serial.print((1000000.0/(float)F_CPU),4);
  Serial.println(F(" us"));

  delay(800);    // Allow the Serial text to be transmitted

  Serial.print(F("  nop                       : "));
  delay(70);     // Allow the Serial text to be transmitted
  m=millis();
  for (i=0; i<100; i++)
  {
    for (j=0; j<10000; j++)
    {
      asm volatile ("nop");
      asm volatile ("nop");
      asm volatile ("nop");
      asm volatile ("nop");
      asm volatile ("nop");
      asm volatile ("nop");
      asm volatile ("nop");
      asm volatile ("nop");
      asm volatile ("nop");
      asm volatile ("nop");
      asm volatile ("nop");
      asm volatile ("nop");
      asm volatile ("nop");
      asm volatile ("nop");
      asm volatile ("nop");
      asm volatile ("nop");
      asm volatile ("nop");
      asm volatile ("nop");
      asm volatile ("nop");
      asm volatile ("nop");
    }
  }
  n=millis();
  d = ((float)n - (float)m) / ((float)i * (float)j);
  d *= 1000.0;           // in micro seconds
  // Calculate overhead with 'nop' instruction per loop in microseconds
  overhead = d - (20.0 * (1000000.0/(float)F_CPU));
  d -= overhead;
  d /= 20.0;             // per instruction
  Serial.print (d,3);
  Serial.println (F(" us"));

  Serial.print(F("  digitalRead               : "));
  delay(70);     // Allow the Serial text to be transmitted
  m=millis();
  for (i=0; i<2; i++)
  {
    for (j=0; j<10000; j++)
    {
      digitalRead(10);       
      digitalRead(10);       

      digitalRead(10);       
      digitalRead(10);       

      digitalRead(10);       
      digitalRead(10);       

      digitalRead(10);       
      digitalRead(10);       

      digitalRead(10);       
      digitalRead(10);       

      digitalRead(10);       
      digitalRead(10);       

      digitalRead(10);       
      digitalRead(10);       

      digitalRead(10);       
      digitalRead(10);       

      digitalRead(10);       
      digitalRead(10);       

      digitalRead(10);       
      digitalRead(10);       
    }
  }
  n=millis();
  d = ((float)n - (float)m) / ((float)i * (float)j);
  d *= 1000.0;
  d -= overhead;
  d /= 20.0;
  Serial.print (d,3);
  Serial.println (F(" us"));



  Serial.print(F("  digitalWrite              : "));
  delay(70);     // Allow the Serial text to be transmitted
  m=millis();
  for (i=0; i<2; i++)
  {
    for (j=0; j<10000; j++)
    {
      digitalWrite(12, HIGH);       
      digitalWrite(12, LOW);       

      digitalWrite(12, HIGH);       
      digitalWrite(12, LOW);       

      digitalWrite(12, HIGH);       
      digitalWrite(12, LOW);       

      digitalWrite(12, HIGH);       
      digitalWrite(12, LOW);       

      digitalWrite(12, HIGH);       
      digitalWrite(12, LOW);       

      digitalWrite(12, HIGH);       
      digitalWrite(12, LOW);       

      digitalWrite(12, HIGH);       
      digitalWrite(12, LOW);       

      digitalWrite(12, HIGH);       
      digitalWrite(12, LOW);       

      digitalWrite(12, HIGH);       
      digitalWrite(12, LOW);       

      digitalWrite(12, HIGH);       
      digitalWrite(12, LOW);       
    }
  }
  n=millis();
  d = ((float)n - (float)m) / ((float)i * (float)j);
  d *= 1000.0;
  d -= overhead;
  d /= 20.0;
  Serial.print (d,3);
  Serial.println (F(" us"));



  Serial.print(F("  pinMode                   : "));
  delay(70);     // Allow the Serial text to be transmitted
  m=millis();
  for (i=0; i<2; i++)
  {
    for (j=0; j<10000; j++)
    {
      pinMode(13, INPUT);       
      pinMode(13, OUTPUT);       

      pinMode(13, INPUT);       
      pinMode(13, OUTPUT);       

      pinMode(13, INPUT);       
      pinMode(13, OUTPUT);       

      pinMode(13, INPUT);       
      pinMode(13, OUTPUT);       

      pinMode(13, INPUT);       
      pinMode(13, OUTPUT);       

      pinMode(13, INPUT);       
      pinMode(13, OUTPUT);       

      pinMode(13, INPUT);       
      pinMode(13, OUTPUT);       

      pinMode(13, INPUT);       
      pinMode(13, OUTPUT);       

      pinMode(13, INPUT);       
      pinMode(13, OUTPUT);       

      pinMode(13, INPUT);       
      pinMode(13, OUTPUT);       
    }
  }
  n=millis();
  d = ((float)n - (float)m) / ((float)i * (float)j);
  d *= 1000.0;
  d -= overhead;
  d /= 20.0;
  Serial.print (d,3);
  Serial.println (F(" us"));



  Serial.print(F("  multiply byte             : "));
  c1 = 2;
  c2 = 3;
  delay(70);     // Allow the Serial text to be transmitted
  m=millis();
  for (i=0; i<20; i++)
  {
    for (j=0; j<10000; j++)
    {
      c1 *= c2;
      c1 *= c2;
      c1 *= c2;
      c1 *= c2;
      c1 *= c2;
      c1 *= c2;
      c1 *= c2;
      c1 *= c2;
      c1 *= c2;
      c1 *= c2;
      c1 *= c2;
      c1 *= c2;
      c1 *= c2;
      c1 *= c2;
      c1 *= c2;
      c1 *= c2;
      c1 *= c2;
      c1 *= c2;
      c1 *= c2;
      c1 *= c2;
    }
  }
  n=millis();
  d = ((float)n - (float)m) / ((float)i * (float)j);
  d *= 1000.0;
  d -= overhead;
  d /= 20.0;
  Serial.print (d,3);
  Serial.println (F(" us"));



  Serial.print(F("  divide byte               : "));
  c1 = 253;
  c2 = 3;
  delay(70);     // Allow the Serial text to be transmitted
  m=millis();
  for (i=0; i<2; i++)
  {
    for (j=0; j<10000; j++)
    {
      c1 /= c2;
      c1 /= c2;
      c1 /= c2;
      c1 /= c2;
      c1 /= c2;
      c1 /= c2;
      c1 /= c2;
      c1 /= c2;
      c1 /= c2;
      c1 /= c2;
      c1 /= c2;
      c1 /= c2;
      c1 /= c2;
      c1 /= c2;
      c1 /= c2;
      c1 /= c2;
      c1 /= c2;
      c1 /= c2;
      c1 /= c2;
      c1 /= c2;
    }
  }
  n=millis();
  d = ((float)n - (float)m) / ((float)i * (float)j);
  d *= 1000.0;
  d -= overhead;
  d /= 20.0;
  Serial.print (d,3);
  Serial.println (F(" us"));



  Serial.print(F("  add byte                  : "));
  c1 = 1;
  c2 = 2;
  delay(70);     // Allow the Serial text to be transmitted
  m=millis();
  for (i=0; i<20; i++)
  {
    for (j=0; j<10000; j++)
    {
      c1 += c2;
      c1 += c2;
      c1 += c2;
      c1 += c2;
      c1 += c2;
      c1 += c2;
      c1 += c2;
      c1 += c2;
      c1 += c2;
      c1 += c2;
      c1 += c2;
      c1 += c2;
      c1 += c2;
      c1 += c2;
      c1 += c2;
      c1 += c2;
      c1 += c2;
      c1 += c2;
      c1 += c2;
      c1 += c2;
    }
  }
  n=millis();
  d = ((float)n - (float)m) / ((float)i * (float)j);
  d *= 1000.0;
  d -= overhead;
  d /= 20.0;
  Serial.print (d,3);
  Serial.println (F(" us"));



  Serial.print(F("  multiply integer          : "));
  volatile int x,y;
  x = 2;
  y = 3;
  delay(70);     // Allow the Serial text to be transmitted
  m=millis();
  for (i=0; i<10; i++)
  {
    for (j=0; j<10000; j++)
    {
      x *= y;
      x *= y;
      x *= y;
      x *= y;
      x *= y;
      x *= y;
      x *= y;
      x *= y;
      x *= y;
      x *= y;
      x *= y;
      x *= y;
      x *= y;
      x *= y;
      x *= y;
      x *= y;
      x *= y;
      x *= y;
      x *= y;
      x *= y;
    }
  }
  n=millis();
  d = ((float)n - (float)m) / ((float)i * (float)j);
  d *= 1000.0;
  d -= overhead;
  d /= 20.0;
  Serial.print (d,3);
  Serial.println (F(" us"));



  Serial.print(F("  divide integer            : "));
  x = 31415;
  y = 3;
  delay(70);     // Allow the Serial text to be transmitted
  m=millis();
  for (i=0; i<1; i++)
  {
    for (j=0; j<10000; j++)
    {
      x /= y;
      x /= y;
      x /= y;
      x /= y;
      x /= y;
      x /= y;
      x /= y;
      x /= y;
      x /= y;
      x /= y;
      x /= y;
      x /= y;
      x /= y;
      x /= y;
      x /= y;
      x /= y;
      x /= y;
      x /= y;
      x /= y;
      x /= y;
    }
  }
  n=millis();
  d = ((float)n - (float)m) / ((float)i * (float)j);
  d *= 1000.0;
  d -= overhead;
  d /= 20.0;
  Serial.print (d,3);
  Serial.println (F(" us"));



  Serial.print(F("  add integer               : "));
  x = 1;
  y = 3;
  delay(70);     // Allow the Serial text to be transmitted
  m=millis();
  for (i=0; i<10; i++)
  {
    for (j=0; j<10000; j++)
    {
      x += y;
      x += y;
      x += y;
      x += y;
      x += y;
      x += y;
      x += y;
      x += y;
      x += y;
      x += y;
      x += y;
      x += y;
      x += y;
      x += y;
      x += y;
      x += y;
      x += y;
      x += y;
      x += y;
      x += y;
    }
  }
  n=millis();
  d = ((float)n - (float)m) / ((float)i * (float)j);
  d *= 1000.0;
  d -= overhead;
  d /= 20.0;
  Serial.print (d,3);
  Serial.println (F(" us"));



  Serial.print(F("  multiply long             : "));
  l1 = 2;
  l2 = 3;
  delay(70);     // Allow the Serial text to be transmitted
  m=millis();
  for (i=0; i<2; i++)
  {
    for (j=0; j<10000; j++)
    {
      l1 *= l2;
      l1 *= l2;
      l1 *= l2;
      l1 *= l2;
      l1 *= l2;
      l1 *= l2;
      l1 *= l2;
      l1 *= l2;
      l1 *= l2;
      l1 *= l2;
      l1 *= l2;
      l1 *= l2;
      l1 *= l2;
      l1 *= l2;
      l1 *= l2;
      l1 *= l2;
      l1 *= l2;
      l1 *= l2;
      l1 *= l2;
      l1 *= l2;
    }
  }
  n=millis();
  d = ((float)n - (float)m) / ((float)i * (float)j);
  d *= 1000.0;
  d -= overhead;
  d /= 20.0;
  Serial.print (d,3);
  Serial.println (F(" us"));



  Serial.print(F("  divide long               : "));
  l1 = 2000000000L;
  l2 = 3;
  delay(70);     // Allow the Serial text to be transmitted
  m=millis();
  for (i=0; i<1; i++)
  {
    for (j=0; j<2000; j++)
    {
      l1 /= l2;
      l1 /= l2;
      l1 /= l2;
      l1 /= l2;
      l1 /= l2;
      l1 /= l2;
      l1 /= l2;
      l1 /= l2;
      l1 /= l2;
      l1 /= l2;
      l1 /= l2;
      l1 /= l2;
      l1 /= l2;
      l1 /= l2;
      l1 /= l2;
      l1 /= l2;
      l1 /= l2;
      l1 /= l2;
      l1 /= l2;
      l1 /= l2;
    }
  }
  n=millis();
  d = ((float)n - (float)m) / ((float)i * (float)j);
  d *= 1000.0;
  d -= overhead;
  d /= 20.0;
  Serial.print (d,3);
  Serial.println (F(" us"));



  Serial.print(F("  add long                  : "));
  l1 = 500000000L;
  l2 = 123;
  delay(70);     // Allow the Serial text to be transmitted
  m=millis();
  for (i=0; i<4; i++)
  {
    for (j=0; j<10000; j++)
    {
      l1 += l2;
      l1 += l2;
      l1 += l2;
      l1 += l2;
      l1 += l2;
      l1 += l2;
      l1 += l2;
      l1 += l2;
      l1 += l2;
      l1 += l2;
      l1 += l2;
      l1 += l2;
      l1 += l2;
      l1 += l2;
      l1 += l2;
      l1 += l2;
      l1 += l2;
      l1 += l2;
      l1 += l2;
      l1 += l2;
    }
  }
  n=millis();
  d = ((float)n - (float)m) / ((float)i * (float)j);
  d *= 1000.0;
  d -= overhead;
  d /= 20.0;
  Serial.print (d,3);
  Serial.println (F(" us"));



  Serial.print(F("  multiply float            : "));
  f1 = 3.24;
  f2 = 1.25;
  delay(70);     // Allow the Serial text to be transmitted
  m=millis();
  for (i=0; i<2; i++)
  {
    for (j=0; j<10000; j++)
    {
      f1 *= f2;
      f1 *= f2;
      f1 *= f2;
      f1 *= f2;
      f1 *= f2;
      f1 *= f2;
      f1 *= f2;
      f1 *= f2;
      f1 *= f2;
      f1 *= f2;
      f1 *= f2;
      f1 *= f2;
      f1 *= f2;
      f1 *= f2;
      f1 *= f2;
      f1 *= f2;
      f1 *= f2;
      f1 *= f2;
      f1 *= f2;
      f1 *= f2;
    }
  }
  n=millis();
  d = ((float)n - (float)m) / ((float)i * (float)j);
  d *= 1000.0;
  d -= overhead;
  d /= 20.0;
  Serial.print (d,3);
  Serial.println (F(" us"));



  Serial.print(F("  divide float              : "));
  f1 = 312645.24;
  f2 = 1.21;
  delay(70);     // Allow the Serial text to be transmitted
  m=millis();
  for (i=0; i<1; i++)
  {
    for (j=0; j<2000; j++)
    {
      f1 /= f2;
      f1 /= f2;
      f1 /= f2;
      f1 /= f2;
      f1 /= f2;
      f1 /= f2;
      f1 /= f2;
      f1 /= f2;
      f1 /= f2;
      f1 /= f2;
      f1 /= f2;
      f1 /= f2;
      f1 /= f2;
      f1 /= f2;
      f1 /= f2;
      f1 /= f2;
      f1 /= f2;
      f1 /= f2;
      f1 /= f2;
      f1 /= f2;
    }
  }
  n=millis();
  d = ((float)n - (float)m) / ((float)i * (float)j);
  d *= 1000.0;
  d -= overhead;
  d /= 20.0;
  Serial.print (d,3);
  Serial.println (F(" us"));



  Serial.print(F("  add float                 : "));
  f1 = 9876.54;
  f2 = 1.23;
  delay(70);     // Allow the Serial text to be transmitted
  m=millis();
  for (i=0; i<1; i++)
  {
    for (j=0; j<10000; j++)
    {
      f1 += f2;
      f1 += f2;
      f1 += f2;
      f1 += f2;
      f1 += f2;
      f1 += f2;
      f1 += f2;
      f1 += f2;
      f1 += f2;
      f1 += f2;
      f1 += f2;
      f1 += f2;
      f1 += f2;
      f1 += f2;
      f1 += f2;
      f1 += f2;
      f1 += f2;
      f1 += f2;
      f1 += f2;
      f1 += f2;
    }
  }
  n=millis();
  d = ((float)n - (float)m) / ((float)i * (float)j);
  d *= 1000.0;
  d -= overhead;
  d /= 20.0;
  Serial.print (d,3);
  Serial.println (F(" us"));


  Serial.print(F("  delay(1)                  : "));
  delay(70);     // Allow the Serial text to be transmitted
  m=millis();
  for (i=0; i<1; i++)
  {
    for (j=0; j<100; j++)
    {
      delay(1);
      delay(1);
      delay(1);
      delay(1);
      delay(1);
      delay(1);
      delay(1);
      delay(1);
      delay(1);
      delay(1);
      delay(1);
      delay(1);
      delay(1);
      delay(1);
      delay(1);
      delay(1);
      delay(1);
      delay(1);
      delay(1);
      delay(1);
    }
  }
  n=millis();
  d = ((float)n - (float)m) / ((float)i * (float)j);
  d *= 1000.0;
  d -= overhead;
  d /= 20.0;
  Serial.print (d,3);
  Serial.println (F(" us"));



  Serial.print(F("  delay(100)                : "));
  delay(70);     // Allow the Serial text to be transmitted
  m=millis();
  for (i=0; i<1; i++)
  {
    for (j=0; j<2; j++)
    {
      delay(100);
      delay(100);
      delay(100);
      delay(100);
      delay(100);
      delay(100);
      delay(100);
      delay(100);
      delay(100);
      delay(100);
      delay(100);
      delay(100);
      delay(100);
      delay(100);
      delay(100);
      delay(100);
      delay(100);
      delay(100);
      delay(100);
      delay(100);
    }
  }
  n=millis();
  d = ((float)n - (float)m) / ((float)i * (float)j);
  d *= 1000.0;
  d -= overhead;
  d /= 20.0;
  Serial.print (d,3);
  Serial.println (F(" us"));

  Serial.println(F("-----------"));
}
                                    
                                

Arduino UNO Node MCU Arduino 101
Controller ATMega328 ESP8266 Intel® Curie™
Frequency 16 MHz 80 MHz 32 MHz
nop 0.063 us 0.013 us 0.031 us
digitalRead 4.902 us 0.540 us 1.350 us
digitalWrite 4.532 us 0.933 us 2.132 us
pinMode 4.342 us 1.455 us 2.630 us
multiply byte 0.632 us 0.100 us 0.318 us
divide byte 5.410 us 0.400 us 1.408 us
add byte 0.443 us 0.100 us 0.284 us
multiply integer 1.387 us 0.148 us 0.347 us
divide integer 14.272 us 0.438 us 1.380 us
add integer 0.883 us 0.135 us 0.284 us
multiply long 6.102 us 0.148 us 0.347 us
divide long 38.662 us 0.447 us 1.400 us
add long 1.763 us 0.135 us 0.285 us
multiply float 7.925 us 0.738 us 0.377 us
divide float 80.162 us 3.772 us 0.350 us
add float 10.112 us 0.683 us 0.380 us
delay(1) 1007.487 us 1024.997 us 1002.500 us
delay(100) 100024.984 us 100025.000 us 100000.000 us

Let me give you a brief about each core in more detail.

The ATmega328/P (found in the Arduino UNO) is a low-power CMOS 8-bit microcontroller based on the AVR® enhanced RISC (reduced instruction set computer) architecture. In Order to maximize performance and parallelism, the AVR uses Harvard architecture – with separate memories and buses for program and data.

The ESP8266 (found in the Node MCU) uses a 32bit processor with 16 bit instructions. It is Harvard architecture which mostly means that instruction memory and data memory are completely separate.

For the Intel® Curie™ module (found in the Arduino 101), it features a dual-core architecture — a host processor and a sensor subsystem — with shared on-die SRAM and flash memory. The host processor is built around a low power 32 MHz Intel® Quark™ SE core, and its instruction set features Intel® archi-tecture and Intel® Pentium® x86 compatibility, with the exception of FPU instructions. Intel have completely given up on its efforts to bring products specific to the Internet of Things. They discontinued the Curie module; along with Intel Edison, Galileo and Joule boards.

The Intel Curie™ seem to be perfect at timing due to its beast dual core processors, and the ESP8266 seem to do more processing in less time because it's attached to much more quick crystal. The ESP8266 can operate up to 160 MHz crystal. I really loved the ESP. I'm goint to use my Node MCU in more future projects.

 Understanding ATTiny44

The board I'm using this week is the board I designed at Week 6. I'll be using the programmer I made in Week 4 to program new code. This board contained ATTiny44 MCU,
  • On GPIO Pin 8 (DB2) there is an LED
  • On GPIO Pin 7 (DA7) there is a Button
The datasheet was pretty long and complex. I really liked this reduced version showing the features of this MCU. Here's what's inside the ATTiny44:

Flash (program memory) 4096 bytes
RAM 256 bytes
EEPROM 256 bytes
GPIO Pins 8 + RST + XTAL1 + XTAL2
ADC Channels 8
PWM Channels 4
Clock options Internal 1/8mhz, external crystal or clock* up to 20mhz
In order to make use of the GPIO pins, we must understand the the architecture first. I found this tutorial very useful, and I'll be quoting and editing the next paragraph, to suit the ATTiny44.
Atmel AVR is 8 bit microcontroller. All its ports are 8 bit wide. Every port has 3 registers associated with it each one with 8 bits. Every bit in those registers configure pins of particular port. Bit0 of these registers is associated with Pin0 of the port, Bit1 of these registers is associated with Pin1 of the port, …. and like wise for other bits. These three registers are as follows : (x can be replaced by A,B,C,D as per the AVR you are using)
  • DDRx register
  • PORTx register
  • PINx register
DDRx register
DDRx (Data Direction Register) configures data direction of port pins. Means its setting determines whether port pins will be used for input or output. Writing 0 to a bit in DDRx makes corresponding port pin as input, while writing 1 to a bit in DDRx makes corresponding port pin as output. Example: to make lower nibble(half byte) of port B as output and higher nibble(half byte) as input : DDRB = 0b00001111;

PINx register
PINx (Port IN) used to read data from port pins. In order to read the data from port pin, first you have to change port’s data direction to input. This is done by setting bits in DDRx to zero. If port is made output, then reading PINx register will give you data that has been output on port pins.

PORTx register
PORTx is used for two purposes:
  1. To output data : when port is configured as output
    When you set bits in DDRx to 1, corresponding pins becomes output pins. Now you can write data into respective bits in PORTx register. This will immediately change state of output pins according to data you have written. Example: PORTB = 0xFF; will write HIGH on every pin that was set as output.
  2. To activate/deactivate pull up resistors – when port is configures as input
    When you set bits in DDRx to 0, i.e. make port pins as inputs, then corresponding bits in PORTx register are used to activate/deactivate pull-up registers associated with that pin. In order to activate pull-up resister, set bit in PORTx to 1, and to deactivate (i.e to make port pin tri stated) set it to 0.
We can visualise the relation between the DDR, PIN, and PORT like following: I'll be trying to program a simple task; which is switching an LED ON and OFF when the button is pressed. I made a flow chart of the sequence: I'll be compiling and uploading with Arduino IDE. I mentioned in Week 4 how to make it ready to handle the code for the ATTiny44. I'll be also using fab ISP I made to upload the code to my board.

 Arduino-C Code

The Arduino code is pretty straightforward. You don't need to remember which DDR, PIN, or PORT. You just set the pinMode in the void setup() section, which will be executed once, then write your code sequence in the void loop() section and it will run repeatedly. Here are some quotes about the most important functions in the Arduino-C language.
pinMode
Configures the specified pin to behave either as an INPUT or an OUTPUT. It is possible to enable the internal pullup resistors with the mode INPUT_PULLUP. Additionally, the INPUT mode explicitly disables the internal pullups.
Syntax: pinMode(pin, state)

digitalWrite
Write a HIGH or a LOW value to a digital pin.
Syntax: digitalWrite(pin, value)

digitalRead
Reads the value from a specified digital pin, either HIGH or LOW.
Syntax: digitalRead(pin)

delay
Pauses the program for the amount of time (in milliseconds) specified as parameter. (There are 1000 milliseconds in a second.)
Syntax: delay(ms)
                                    
void setup() {
    pinMode(8, OUTPUT);
    pinMode(7, INPUT_PULLUP);
}

void loop() {
    if (!digitalRead(7))
    {
        digitalWrite(8, HIGH);
        delay(1250);
        digitalWrite(8, LOW);
        delay(1250);
    }
}
                                    
                                
In the If statement, there is a (!) mark before the digitalRead. This mark is for inverting the logic. The digitalRead(7) returns HIGH when the button is unpressed because we defined the input pin to be pulled-up, and it will be inverted so that the If statement won't be executed when the button is not pressed.

When the button is pressed, the input pin will be connected to the ground; making digitalRead(7) returns LOW which will be inverted by the (!) mark to HIGH, causing the If statement to execute.

I uploaded the code to my board using FabISP like I explained before in Week 4 and it worked fine, as in the video shown above.

 AVR-C Code

The AVR-C code would be very similar to the previous code, except for it would be more detailed. It's needed to define everything related to the DDR, PIN, and PORT.

It begins by defining the clock speed
#define F_CPU 20000000UL
Then including the default libraries for the AVR MCUs and for timing #include <avr/io.h> #include <util/delay.h>
The next thing to do is to define the int main(void) function, which will be executed directly when the MCU is powered. Inside this fucntion, we can write any sequence we want for the code. The code written inside the main is executed only for one time.

The DDRB = 0b00000100; line, will configure Pin 2 at Port B as Output.
The PORTA = 0b10000000; line, will Pull-up Pin 7 at Port A.
This part of the code is similar to the code written in the void setup() function in the Arduino-C code.

Since the main code is only executed once, we need to nest our repeating sequence in a loop. This is done by using while(1) infinite loop, where we can nest the condition and the ON/OFF sequence.

The condition is simple: if (!(PINA & (0b10000000))). The PINA reads the whole pins byte (A). In order to read a specifi pin, we should just ignore the rest of the pins by anding them with zeros. When the required pin is connected to GND the expression result will be !(0) which is 1, and vice versa.

Now, we can just use PORTB |= 0b00000100; to output logic 1 on Pin 2 at Port B; leaving the other pins in whatever state. This is because (0) | 0 = 0 and (1) || 0 = 1
and PORTB &= 0b11111011; outputs logic 0 on Pin 2 at Port B, leaving the other pins in whatever state, because (0) & 1 = 0 and (1) & 1 = 1

After truning On of Off the output pin, we need a delay to see the effect. This is done by using _delay_ms(1250); , which is similar to the delay(ms) function in the Arduino-C.

and here's the full code:

                                    
#define F_CPU 20000000UL
#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
    DDRB   = 0b00000100;      //Configured Pin 2 at Port B as Output
    PORTA  = 0b10000000;      //Pull-up Pin 7 at Port A.
    while (1)
    {
        if (!(PINA & (0b10000000)))
        {
            // Output logic 1 on Pin 2 at Port B
            PORTB |= 0b00000100;  
            
            _delay_ms(1250); 
            
            // Output logic 0 on Pin 2 at Port B
            PORTB &= 0b11111011;  
            
            _delay_ms(1250);       
        }
    }
}
                                        
                                    
                                

I uploaded the code to my board using FabISP like I've mentioned before. I got the same result exactly like the previous example.

 iArduino Interpreter

Can we expand the Flash (Program Memory) of the AVR MCU?
I asked the internet this interesting question, and I learned that this is an known concept called Code Paging. And this concept is applicable at computers because there is an operating system that handles all the necessary operations in order to do that.

After further searches, I came to the concept of making the MCU act like an Interpreter that can execute the code saved in the EEPROM. I was mind-blown by this concept. It's really smart. You use the Flash for the Interpreter only, and make it retrive and execute your code from the internal EEPROM, or even an external one. This approach might seem slower, but in terms of space utility, it's really efficient.

I decided to give it a try, and found so many Interpreters that can work over the Arduino UNO, because of the 32Kb of Flash space. Here's a list of my findings:
  • iArduino: a C Interpreter for Arduino
  • Bitlash: a programmable command shell for arduino
  • uBASIC: a really simple BASIC interpreter
  • uLisp: Lisp for microcontrollers
  • ArduinoBASIC: A BASIC interpreter & environment for the Arduino
After having a tour in the features and documentations for each of them, I became really interested in the iArduino interpreter. It's really old, but the library compiled just fine.

I made a one-minute video where I send the commands from the terminal and they get executed. I also tried to write a full program and save it to the EEPROM, and I also worked very fine.

I'm planning to customize this firmware in my final project. I'm really glad that I found this gem : D