A New Beginning

by Conrad Gomes on

Epoch

TechEuphoria was developed during the second quarter of 2014 with the help of a wonderful slide deck from an open source advocate Dan Allen(mojavelinux).

Objectives

I had an overall understanding of what I wanted to achieve. It is to build a lean and clean website, have the ability to be agile and publish with ease and at will. My objectives took form over the course of my search for a solution as I became familiar with the different concepts and paradigms of web design and development. My objectives can now be summarized as follows:

  1. Use a decentrallized tool with which TechEuphoria can be built locally before publishing it to the world wide web.

  2. The tools chosen should have a mechanism with which the presentation of the website could be separated from the content.

  3. Use responsive website design(RWD) to allow users with devices of different displays to consume the content.

A Journey of Errors

My objectives were more or less clear. I needed a way to work on my website, whenever and wherever I wanted to. I knew Git was a good way to achieve it but I did not know about Github Pages and started off with the first choice that came to mind and that was Wordpress.

So begain my pursuit to build TechEuphoria with the objectives given. I initially figured a way to deploy and manage this website with the help of the following links:

After days of playing around and understanding the details of Wordpress I realized that it was still difficult to publish and the fact of dumping the SQL database to a file to sync different copies of the website was a hack rather than a solution. Despite getting the solution working I abandoned it completely on the 30th of May. My exploits are stored in the logs of the following repositories:

Tools

The following represents the tools that I use to compile and publish this website:

  1. TechEuphoria content is written in AsciiDoc.

  2. It is transformed by Awestruct and Asciidoctor into a static website.

  3. It uses Github Pages as its publishing engine.

  4. I use Vim as my text editor to edit everything.

  5. My development machine is an Ubuntu guest on an Oracle Virtual Box

Happy Blogging!


Printing the Linux kernel version

by Conrad Gomes on

The kernel version that a kernel module is built with can differ from the kernel version it is running on. The version of the kernel that the module is running on is shown in the first log and the version of the kernel is compiled with is shown in the second log in the version_init function:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/utsname.h>
#include <generated/utsrelease.h>

static int __init version_init(void)
{
        int i = 0;

        pr_alert("Kernel module running of version %s\n", utsname()->release);
        pr_alert("Kernel module compiled with version %s\n", UTS_RELEASE);
        return 0;
}

static void __exit version_exit(void)
{
        pr_alert("Over and out!\n");
}

module_init(version_init);
module_exit(version_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("zeuzoix");
MODULE_DESCRIPTION("Kernel Module Version Example Module");

Caches

by Conrad Gomes on

Let’s talk about the cache and its requirement in a computing system. The word cache is derived from the french word cacher which means to hide.

In a nutshell it’s a memory subsystem which improves the speed of execution of a thread by providing faster access to instructions and data based on their temporal and spacial characteristics in the program.

With memory there’s typically a trade off between space and time. If speed is required then the storage capacity of the memory reduces particularly because the cost of the memory goes up with speed.

So system designers often incorporate a cache in between the processor and main memory which can significantly improve the speed at which memory access occurs.

The cache can be of different levels typically most processors these days have an inbuilt cache termed as L1 which is the smallest memory device in the hierarchy of memory in the system. Some processors like ARM Cortex’s A series have an in built L2 cache also.

There are several popular designs for caches. The following videos give a very nice description of the different types of caches:


Linux Linked Lists

by Conrad Gomes on

The linux kernel has a very peculiar implementation of the linked lists data structure. The linked list is actually a circular linked list. The following article is useful in understanding more about the design:
http://kernelnewbies.org/FAQ/LinkedLists

What’s interesting is that the entire implementation is conveniently located in one header file. This shows that the open source movement when done right gives you the best solution possible over time:
http://lxr.free-electrons.com/source/include/linux/list.h


I2C/TWI with AVR Data Transfer

by Conrad Gomes on

We now take a look at the TWI/I2C API responsible for data transfer. The header file twi.h has the prototype. We’ll take a look at the arguments and their description now:

TWI_RET_E twi_send_recv_buffer(
                           TWI_SEND_RECV_BUFFER_PARAMS_X *px_send_buffer_params,
                           TWI_MODE_E e_mode);

The first argument is a pointer to TWI_SEND_RECV_BUFFER_PARAMS_X defined as follows:

typedef struct _TWI_SEND_RECV_BUFFER_PARAMS_X
{
   uint8_t uc_dev_addr;
   uint8_t uc_dev_id;
   uint8_t *puc_reg_addr;
   uint32_t ui_reg_addr_sz;
   uint8_t *puc_data;
   uint32_t ui_data_sz;

}TWI_SEND_RECV_BUFFER_PARAMS_X;

Where

  1. uc_dev_addr is the higher nibble of the I2C slave device address

  2. uc_dev_id is the lower nibble of the I2C slave device address. It is used where the slave address can be configured

  3. puc_reg_addr is the pointer to the buffer holding the register address of the slave device.

  4. ui_reg_addr_sz is the size of the buffer with the register address.

  5. puc_data is the pointer to the data buffer

  6. ui_data_sz is the size of the data buffer.

The second argument is an enumeration which indicates if a send or receive operation is to be done

typedef enum _TWI_STATE_MODE_E
{
   eTWI_MODE_READ = 0,
   eTWI_MODE_WRITE,
   eTWI_MODE_INVALID

}TWI_MODE_E;

I2C/TWI with AVR Register Initialization

by Conrad Gomes on

We learned about the different registers available in the Atmel AVR microcontroller to program the TWI interface. In this section we’ll go through the twi_init API and the initialization of the TWI interface.

The initialization code in the testbench.c initializes the TWI/I2C library as follows:

x_twi_init_params.e_mode = eTWI_INIT_MODE_16_0000M_100K_1;
x_twi_init_params.pfn_debug = testbench_debug;
e_twi_ret = twi_init(&x_twi_init_params);
if(eTWI_SUCCESS != e_twi_ret)
{
   i_ret = -1;
   goto LBL_INIT_IO_RET;
}

The API twi_init takes a structure variable x_twi_init_params of the type shown below. The definition is in twi.h:

typedef struct _TWI_INIT_PARAMS_X
{
   TWI_INIT_MODE_E e_mode;
   TWI_DEBUG_PFN pfn_debug;

}TWI_INIT_PARAMS_X;

The TWI interface can be initialized based on several modes each of which is given an identifier which signifies the CPU clock frequency, SCL clock speed and the pre-scaler value. For instance in the enumeration definition below eTWI_INIT_MODE_16_0000M_100K_1 is the mode for a 16.0000MHz micro-controller, with the desired SCL clock frequency set at 100KHz and the pre-scaler set to 1.

typedef enum _TWI_INIT_MODE_E
{
   eTWI_INIT_MODE_16_0000M_100K_1 = 0,
   eTWI_INIT_MODE_16_0000M_400K_1,
   eTWI_INIT_MODE_16_0000M_100K_4,
   eTWI_INIT_MODE_16_0000M_400K_4,
   eTWI_INIT_MODE_INVALID

}TWI_INIT_MODE_E;

Internally if we take a look at the twi_init function defined in twi.c we see a look up table is employed to initialize the 5 registers TWBR, TWCR, TWSR, TWDR, TWAR. The look up table has the following structure for each row:

typedef struct _TWI_INIT_REG_X
{
   TWI_INIT_MODE_E e_mode;
   uint8_t uc_twbr;
   uint8_t uc_twcr;
   uint8_t uc_twsr;
   uint8_t uc_twdr;
   uint8_t uc_twar;

}TWI_INIT_REG_X;

The lookup table is a global array gxa_init_reg and is defined as follows:

static TWI_INIT_REG_X gxa_init_reg[] =
{
   {
      eTWI_INIT_MODE_16_0000M_100K_1,
      0x48,                               //0b01001000
      0x80,                               //0b10000000
      0x00,                               //0b00000000
      0x00,                               //0b00000000
      0x00                                //0b00000000
   }
};

The code in twi_init cycles through the array gxa_init_reg until it finds the correct mode and then initializes the 5 registers with the values associated with the mode.

for(uc_i = 0 ; uc_i < uc_size_arr ; uc_i++)
{
   if(px_init_params->e_mode == gxa_init_reg[uc_i].e_mode)
   {
      px_init_reg = &gxa_init_reg[uc_i];
      break;
   }
}

if(NULL == px_init_reg)
{
   if(NULL != px_init_params->pfn_debug)
   {
      px_init_params->pfn_debug("Can't find correct mode");
   }

   e_ret = eTWI_FAILURE;
   goto LBL_TWI_INIT_RET;
}

TWBR = px_init_reg->uc_twbr;
TWCR = px_init_reg->uc_twcr;
TWSR = px_init_reg->uc_twsr;
TWDR = px_init_reg->uc_twdr;
TWAR = px_init_reg->uc_twar;

In the next section we’ll check out transmit and receive functionality on the TWI/I2C bus with I2C/TWI with AVR Data Transfer.


I2C/TWI with AVR Register Descriptions

by Conrad Gomes on

So you want to program the TWI/I2C interface of the AVR. Well you’ll need to read up about the registers used to control this interface. Though the microcontroller uses two pins SDA and SDC to drive the bus there is a bunch of registers which are used to control the pins themselves. Let’s take a look at them.

TWI Bit Rate Register (TWBR)

This register controls the SCL clock frequency which can either be 100Hz or 400Hz.

TWI TWBR
Figure 1. TWI bit rate register map

The equation to set the correct SCL clock frequency is:

svg.latex
Figure 2. SCL clock frequency equation
  1. CPUclockfreq is the CPU clock frequency(16MHz in my case).

  2. SCLfreq is the desired SCL clock frequency(100Hz in my case).

  3. TWBR is the value we store in the register.

  4. TWPS is the prescaler bits in the TWI status register TWSR which can take values from 0 to 3(0 in my case).

TWI Control Register (TWCR)

This register is used to control the operation of the TWI/I2C interface. Start or stop a transaction and acknowledge the receipt of a data packet.

TWI TWCR
Figure 3. TWI control register map
  1. Bit 7 - TWINT: Set when the TWI has finished it’s task. Also used to initiate a transaction. This flag is normally cleared by writing a 1 to it. All other operations to the TWDR and TWAR must be done before this is cleared.

  2. Bit 6 - TWEA: Controls generation of the acknowledge bit.

  3. Bit 5 - TWSTA: Controls generation of a start bit.

  4. Bit 4 - TWSTO: Controls generation of a stop bit.

  5. Bit 3 - TWWC: This is a read only bit. It is set if you write TWDR when TWINT is low. It is reset if you write TWDR when TWINT is high.

  6. Bit 2 - TWEN: This bit enables the TWI/I2C interface

  7. Bit 0 - TWIE: This bit in conjunction with the I-bit in SREG enables the interrupt mode

TWI Status Register (TWSR)

After every operation of the TWI interface this register is read to understand the status of the bus.

TWI TWSR
Figure 4. TWI status register map
  1. Bits 7:3 - TWS7:TWS3: Status of the last TWI/I2C transaction

  2. Bits 1:0 - TWPS1:TWPS0: These are the pre-scaler bits used to modify the SCL frequency.

TWI Data Register (TWDR)

This register is used to stores the bytes to be transmitted or the bytes received on the TWI bus.

TWI TWDR
Figure 5. TWI data register map
  1. Bits 7:0 - TWD7:TWD0: Data byte to be written to the TWI bus or read from the TWI bus.

TWI Address Register (TWAR)

This register is loaded with the 7 bit Slave address to which it must respond to when programmed as a slave or when working in a multiple master mode. In the multiple master mode the device will compete to be a master and if it senses that it has lost the arbitration of the line it will have to turn into a slave and listen for a possible message from another master device.

TWI TWAR
Figure 6. TWI address register map
  1. Bits 7:1 - TWA6: TWA0: 7 bit slave address of the TWI interface.

  2. Bit 0 - TWGCE: Indicates if the device will acknowledge a general call when sent. A general call is an address to all the slaves connected on the bus. The Slave address for a general call is usually all 0s.

In the next section I2C/TWI with AVR Register Intialization we’ll go through the initialization code for the TWI/I2C interface and the values assigned to these registers.


I2C/TWI with AVR Introduction

by Conrad Gomes on

In this post we’ll take a look at implementing an I2C/TWI library which can be used with Atmel’s AVR micro-controller.

The code has been uploaded to GitHub at https://github.com/zeuzoix/sardine and will be referenced here. The TWI library consists of the following files:

  1. twi.h

  2. twi.c

  3. twi_states.h

  4. twi_states.c

  5. twi_debug.h

There are two API which the application can use to interface with the I2C/TWI interface. The prototypes are in twi.h

   uint32_t ui_data_sz;

}TWI_SEND_RECV_BUFFER_PARAMS_X;


TWI_RET_E twi_init(TWI_INIT_PARAMS_X *px_init_params);
TWI_RET_E twi_send_recv_buffer(TWI_SEND_RECV_BUFFER_PARAMS_X *px_send_buffer_params,
                               TWI_MODE_E e_mode);

#endif

The first API twi_init is used to initialize the TWI interface in master mode by assigning a set of register values to the TWI registers in the AVR Atmel micro-controller.

The second API twi_send_recv_buffer is used in both transmit and receive mode to send and receive data over the TWI SDA data line.

We’ll take a look at the registers used in the programming of the TWI interface in the next section i.e.


GIT

by Conrad Gomes on

I’ve been a SVN user for quite some time. However it’s good to understand why GIT has risen in popularity.

GIT was developed by the same team that developed Linux. Key differences as compared to other version control systems

  1. Distributed: Everyone gets access to the repository on their system unlike other version control systems which have a central repository on a server. The main advantage being that even if network access is not available you can still interact with the version control system.

  2. Snapshots: A version of a file is the snapshot of the file at that point in time. It is not the sum of all differences. Basically the smallest unit of change is a file.


Real Time Clock with DS1307 - Register Map Description

by Conrad Gomes on

In the first part we went through a brief introduction of the DS1307 chip.
We know the DS1307 can be programmed via the I2C bus i.e SDA and SCL. Through I2C we should be able to address the registers of this chip and write and read data based on our application description.

The internal registers which affect the behaviour of the RTC chip are as follows:

DS1307 RegisterMap
Figure 1. Register map of the DS1307 RTC

The first 7 registers are used to read and write the time and date. Registers 00h and 01h have more or less the same byte definition and this is mainly because there are 60 seconds and 60 minutes.

An important difference is bit 7 of register 00h which is the clock halt bit. By default this bit is set to 1 on power up of the device which disables the oscillator and RTC functionality of the DS1307.

All values are in binary coded decimal. The range of seconds and minutes goes from 00 to 59. Therefore for the minutes and seconds we have bits 0 to 3 representing the lower digit i.e. 0 to 9 and bits 4 to 6 representing the higher digit.

The representation of hours can be in the form of either 12 or 24 hour notation. Bit 6 indicates the notation used. When high the 12 hour notation is used and bit 5 indicates AM/PM with high being PM. In this case the range of values goes from 01 to 12. Therefore we have bits 0 to 3 representing the lower digits i.e. 0 to 9 and bit 4 representing the higher digit i.e. 0 or 1.

In the 24 hour notation the range of values goes from 00 to 23. Therefore the lower digit representation remains the same i.e. 0 to 9 represented by bits 0 to 3 but bits 4 and 5 are used to represent the higher digit i.e. 0 to 2.

Essentially the number of bits reserved for each digit is defined by the range of the value. For instance there are only 7 possible days and so we have 3 bits representing the day of the week in register 03h. And if we look at the date register 04h we see the range of values goes from 01 to 31 therefore the lower digit of the date can have a maximum value of 9 so four bits are reserved whereas the upper digit can have a maximum value of 3 therefore 2 bits are reserved.

Registers 05h and 06h follow the same pattern. Register 07h controls the behaviour of the square wave out signal. Bit 4 controls the functionality i.e. whether the pin produces a square wave or a fixed ouput. By default the value is 0 causing the pin to output a fixed value governed by the bit 7. If bit 4 is set to 1 the pin produces a square wave whose frequency is controlled by bits 0 and 1. The number of possible combinations is 4 with 2 bits and therefore the possibilities are 1Hz, 4.096kHz, 8.192kHz and 32.768kHz.

Registers 08h to 3Fh provide a 56x8 RAM area for use by the application. For further information please go through the data sheet at: ds1307-maximintegrated-pdf