Tuesday, August 13, 2013

ATMega128 and Nokia 1202 LCD

Nokia 1202/1203/1280 LCD is small, cheap and easy to interface with. It has 12 pins (face side, pins up from the left to the right):
  1. NC
  2. RESET
  3. CS
  4. GND
  5. SDA
  6. SCL
  7. VDD 3.3 V
  8. VDD 3.3 V
  9. GND
  10. LED- (GND)
  11. LED+ 3.3 V
  12. NC
Connecting Nokia 1202 LCD to ATMega128:
There are many various library implementations for this display, you may download one of them here (Nokia 1100 LCD library updated to work with Nokia 1202 display by Chiper http://digitalchip.ru/):

Wednesday, July 3, 2013

Accessing 24LC512 EEPROM: TWI/I2C emulation

Theory
Please refer to official 24LC512 specification and appropriate article at the Wikipedia for detailed information on 24LC512 EEPROM and theoretical vision of TWI/I2C protocol:






Practice
The following connection scheme and code is intended to be used with Atmel AT90USB162 MCU. First of all, we need to choose which MCU pins will be our SCL and SDA lines, I have chosen PB1 (pin 15) for SCL and PB2 (pin 16) for SDA. Refer to the Fritzing circuit in the previous post for connection scheme.

Define ports:
#define SCLPORT  PORTB
#define SCLDDR  DDRB

#define SDAPORT  PORTB
#define SDADDR  DDRB

#define SDAPIN  PINB
#define SCLPIN  PINB

#define SCL  PB1
#define SDA  PB2
SCL and SDA signal edges:
#define TWI_SDA_LOW SDADDR |= (1 << SDA)
#define TWI_SDA_HIGH SDADDR &= ~(1 << SDA)

#define TWI_SCL_LOW SCLDDR |= (1 << SCL)
#define TWI_SCL_HIGH SCLDDR &= ~(1 << SCL)
24LC512 commands, ACK/NACK (acknowledge) and delays definitions:
#define _24LC512_WRITE  0b10100000
#define _24LC512_READ   0b10100001

#define ACK_ACK         1
#define ACK_NACK        0

#define Q_DEL           _delay_loop_2(3);
#define H_DEL           _delay_loop_2(5);
TWI/I2C commands (Init/Start/Stop/Write/Read):
void TWI_Init (void) {
    SDAPORT &= ~(1 << SDA);
    SCLPORT &= ~(1 << SCL);
    TWI_SDA_HIGH;   
    TWI_SCL_HIGH;
}

void TWI_Start (void) {
    TWI_SCL_HIGH;
    H_DEL;
    TWI_SDA_LOW;
    H_DEL;
}

void TWI_Stop (void) {
    TWI_SDA_LOW;
    H_DEL;
    TWI_SCL_HIGH;
    Q_DEL;
    TWI_SDA_HIGH;
    H_DEL;
}

uint8_t TWI_Write (uint8_t Data) {
    uint8_t i;
    uint8_t ACK;
    for (i = 0; i < 8; i++) {
        TWI_SCL_LOW;
        Q_DEL;
        if (Data & 0x80) {
            TWI_SDA_HIGH;
        }
        else {
            TWI_SDA_LOW;
        }
        H_DEL;
        TWI_SCL_HIGH;
        H_DEL;
        while ((SCLPIN & (1 << SCL)) == 0);
        Data = Data << 1;
    }
    TWI_SCL_LOW;
    Q_DEL;
    TWI_SDA_HIGH;
    H_DEL;  
    TWI_SCL_HIGH;
    H_DEL;
    ACK = !(SDAPIN & (1 << SDA));
    TWI_SCL_LOW;
    H_DEL;
    return ACK;
}

uint8_t TWI_Read (uint8_t ACK) {
    uint8_t Data = 0x00;
    uint8_t i;
    for (i = 0; i < 8; i++) {
        TWI_SCL_LOW;
        H_DEL;
        TWI_SCL_HIGH;
        H_DEL;  
        while ((SCLPIN & (1 << SCL)) == 0);
        if (SDAPIN & (1 << SDA)) {
            Data |= (0x80 >> i);
        }
    }
    TWI_SCL_LOW;
    Q_DEL;
    if (ACK) {
        TWI_SDA_LOW;
    }
    else {
        TWI_SDA_HIGH;
    }
    H_DEL;
    TWI_SCL_HIGH;
    H_DEL;
    TWI_SCL_LOW;
    H_DEL;
    TWI_SDA_HIGH;
    return Data;
}
Finally, functions for accessing 24LC512 EEPROM:
uint8_t _24LC512_WriteByte (uint16_t Address, uint8_t Data) {
    TWI_Start();
    if (!TWI_Write(_24LC512_WRITE)) {
        TWI_Stop();
        return FALSE;
    }
    if (!TWI_Write(Address >> 8)) {
        TWI_Stop();
        return FALSE;
    }
    if (!TWI_Write(Address)) {
        TWI_Stop();
        return FALSE;
    }
    if (!TWI_Write(Data)) {
        TWI_Stop();
        return FALSE;
    }
    TWI_Stop();
    _delay_ms(5);
    return TRUE;
}

uint8_t _24LC512_WritePage (uint16_t Address, uint8_t* Page, uint8_t Count) {
    TWI_Start();
    if (!TWI_Write(_24LC512_WRITE)) {
        TWI_Stop();
        return FALSE;
    }
    if (!TWI_Write(Address >> 8)) {
        TWI_Stop();
        return FALSE;
    }
    if (!TWI_Write(Address)) {
        TWI_Stop();
        return FALSE;
    }
    while (Count--) {
        if (!TWI_Write(*Page++)) {
            TWI_Stop();
            return FALSE;
        }
    }
    TWI_Stop();
    _delay_ms(5);
    return TRUE;
}

uint8_t _24LC512_ReadByte (uint16_t Address, uint8_t* Data) {
    TWI_Start();
    if (!TWI_Write(_24LC512_WRITE)) {
        TWI_Stop();
        return FALSE;
    }
    if (!TWI_Write(Address >> 8)) {
        TWI_Stop();
        return FALSE;
    }
    if (!TWI_Write(Address)) {
        TWI_Stop();
        return FALSE;
    }
    TWI_Start();
    if (!TWI_Write(_24LC512_READ)) {
        TWI_Stop();
        return FALSE;
    }
    *Data = TWI_Read(ACK_NACK);
    TWI_Stop();
    return TRUE;
}

uint8_t _24LC512_ReadPage (uint16_t Address, uint8_t* Page, uint8_t Count) {
    TWI_Start();
    if (!TWI_Write(_24LC512_WRITE)) {
        TWI_Stop();
        return FALSE;
    }
    if (!TWI_Write(Address >> 8)) {
        TWI_Stop();
        return FALSE;
    }
    if (!TWI_Write(Address)) {
        TWI_Stop();
        return FALSE;
    }
    TWI_Start();
    if (!TWI_Write(_24LC512_READ)) {
        TWI_Stop();
        return FALSE;
    }
    Count--;
    while (Count--) {
        *Page++ = TWI_Read(ACK_ACK);
    }
    *Page++ = TWI_Read(ACK_NACK);
    TWI_Stop();
    return TRUE;
}
That's it, very simple.
Download full library sources:

Saturday, June 22, 2013

Keyring project version 1.0

Background
I have too many passwords to keep them in mind, so one day I have decided to develop my own hardware secured password storage. It should have met the following requirements to satisfy my needs:
  1. Usability: hardware and software should be simple in usage and maintenance.
  2. Security: it should have basic internal pseudo-encryption (it is enough for the first version) and it should not store master password.
  3. Storage: device should be able to store about a hundred passwords at a minimum.
  4. Performance: password retrieve time should not exceed 1 second.
  5. Sizes: device with enclosing should have typical size of USB stick.
  6. Price: should not exceed $30.00.
I believe there are many analogues presented at the market and you may find many varieties of encrypted storage, here are couple of examples:
But the idea is to focus on passwords and descriptions for them (addresses, URLs, devices, etc.), current, full and, I hope, final name of the project is OWLSAN Keyring.





Architecture
The next step was to define architecture. Omitting the details and reasons of my choice, I have finally decided on implementing basic client-server architecture, where the client is user's PC and the server is Keyring device.
On the client side there is a small program in Python, which sends requests to Keyring device via USB, retrieves replies and fetches data. Server side receives requests, performs required actions and sends back replies.
Refer to the table 1 for Keyring Interaction Protocol (KIP) commands, to the table 2 for KIP statuses and to the table 3 for KIP variable sizes.


Command
Value
Description
ACCESS
0
Accesses Keyring using master password. Authentication should be done using this command prior to performing any other actions, otherwise FAIL status will be returned for every action.
Session is initially set by this command and should be used for further interaction by UI.

Request:
[Command][Session][Master password]
Reply:
[Command][Status]
LIST
1
Returns the list of record statuses chunk-by-chunk – returns the specified chunk of statuses.

Request:
[Command][Session][Chunk number]
Reply:
[Command][Status][Chunk list]
READ
2
Reads record data. Full reading should be done in two steps: first reply contains description, the second one contains password.

Request:
[Command][Session][Number]
Reply:
[Command][Status][Description] – after the first request
[Command][Status][Password] – after the second request
WRITE
3
Writes data to the specified record.

Request:
[Command][Session][Number][Description][Password]
Reply:
[Command][Status]
DELETE
4
Deletes specified record.

Request:
[Command][Session][Number]
Reply:
[Command][Status]
MASTER
5
Changes master password. Device should not be disconnected/powered off during this operation, otherwise data integrity is not guaranteed.

Request:
[Command][Session][New master password]
Reply:
[Command][Status]
FORMAT
6
Formats Keyring – clears data and resets master password to default – “OWLSANKEYRING”.

Request:
[Command][Session]
Reply:
[Command][Status]
FLUSH
7
Flushes number flag for READ command – service command.

Request:
[Command][Session]
Reply:
[Command][Status]
RESET
8
Resets Keyring – clears access flag and session (sign out analogue).

Request:
[Command][Session]
Reply:
[Command][Status]
PROGRAM
9
Sets programming flag, device enters DFU bootloader after the next reset.

Request:
[Command][Session]
Reply:
[Command][Status]
Table 1

Status
Value
Description
FAIL
0
Command execution has failed
DONE
1
Command performed successfully
Table 2

Variable
Size, bytes
Description
Command 1 Refer to table 1 for the list of available commands.
Session 4 Unique ID that should be assigned to the connection on every ACCESS command invocation.
Status 1 Refer to table 2 for the list of available statuses.
Number 4 Record number – number of pair description + password.
Description 32 Description (hint) for the password.
Password/Master password 16
Chunk number 4 Number of record list status chunk.
Chunk list 32 List of record statuses. Refer to table 4 for KIP record statuses details.
Table 3

Record status
Value
Description
FREE
0
Record space is free
DATA
1
Record space contains data
CORRUPTED
2
Corrupted record space – cannot be verified
Table 4

Notes:
  1. Master password is not stored anywhere, only its hash in order to authenticate user.
  2. Default master password is equal to signature – “OWLSANKEYRING” (uppercase, without quotes).
  3. USB data packet size is 64 bytes.
Internal and external EEPROM structure is presented in the table 5.

Location
Offset, bytes
Item
Internal 0 Signature – “OWLSANKEYRING” (w/o quotes)
Internal 128 Master password CRC32 hash
Internal 256 Programming flag
External 0 CRC32 hash table – used in CRC32 calculations
External 1024 Records statuses list
External 2048 Records data
Table 5






Hardware
Hardware core of the Keyring is Atmel AT90USB162 MCU (image 1), it has several important features which meet my initial requirements:
  1. Size – 7x7x1 mm in TQFP32 package.
  2. Price – $5 per unit.
  3. Performance – up to 16 MIPS at 16 MHz.
  4. Interface – USB 2.0.
  5. Storage – 16 kbytes of flash, 512 bytes of internal EEPROM.
Also it has DFU bootloader which will make your life easier with programming FLIP software – you don't need to use serial programmer anymore.
As a storage unit I have utilized Microchip 24LC512 I2C EEPROM (image 2), which has 512 kbits (64 kbytes) of memory – quite enough to store a hundred of passwords with their short descriptions (hints):
  1. Size – 6x4.9x1.25 mm in SOIC8 package.
  2. Price – $3 per unit.
  3. Performance – page (128 bytes) write time is 5 ms max.
  4. Interface – TWI/I2C.
  5. Storage – 65536 bytes.
Image 2
Image 1
Image 2
Image 2
The other required components are:
  • 22 Ohm resistors for MCU USB data lines
  • 4.7 uF bypass capacitor for MCU USB
  • 16 MHz quarz for MCU
  • 22 pF load capacitors for quartz
  • 100 nF ceramic (fast) and 4.7 uF bypass capacitors
  • 4.7 kOhm pull-up resistors for EEPROM
  • USB-A SMD connector
  • Material for PCB
  • Enclosure
Refer to table 6 for bill of material.
 
Type
Component
Count
Price per unit, $
Total price, $
MCU
AT90USB162
1
5.04
5.04
EEPROM
24LC512
1
2.94
2.94
Quartz
HC-49/SMD 16 MHz
1
2.58
2.58
Capacitor
22 pF
2
0.02
0.04
Capacitor
100 nF
2
0.05
0.10
Capacitor
4.7 uF
2
0.05
0.10
Resistor
22 Ohm
2
0.01
0.02
Resistor
4.7 kOhm
2
0.01
0.02
Connector
USB-A SMD
1
1.83
1.83
PCB material
Glass textolite
1.00
1.00
Enclosure
Plastic box
1
2.00
2.00

15.67
Table 6

For enabling DFU programmer you will also need to implement HWB (hardware boot) and RST (reset) buttons. Take a look at image 3 for complete circuit – moreover, it shows connections to FT232RL board for serial programming. Image 4 depicts circuit after assembling components on the breadboard.
Image 3
Image 3
Image 4
Image 4





Firmware
Keyring Firmware utilizes LUFA library for interaction via USB interface. AT90USB162 MCU does not have “native” TWI/I2C interface for interaction with 24LC512 EEPROM chip, so the corresponding library is implemented to emulate it.
Keyring Firmware consists of the following modules:

  • LUFA
  • TWI/I2C firmware library
  • Core firmware
Core initializes hardware, checks signature integrity and starts “listening”: when USB data buffer is filled, it is parsed by core and processing cycle is done, after that core awaits when the buffer will be filled again.
TWI/I2C library pins are mapped to hardware pins the following way:

  • SCL – pin 15 (PB1)
  • SDA – pin 16 (PB2)





Software
Keyring Software is simple and written in Python, it utilizes PyUSB library and PyQt and consists of the following components:
  • PyQt
  • PyUSB library
  • Core library
  • Core software
Keyring Software implements the following functionality:
  1. Connect – authenticate at the Keyring (image 5).
  2. Reset – sign out and disconnect.
  3. Browse records (image 6).
  4. View password (image 7).
  5. Edit record (images 8-9).
  6. Delete record (image 8).
  7. Add record (image 10).
  8. Set master password (image 11).
  9. Format device.
Image 5
Image 5
Image 6
Image 6
Image 7
Image 7
Image 8
Image 8
Image 9
Image 9
Image 10
Image 10
Image 11
Image 11
 




Schematics
I have designed two variants of PCB schematics:
  • Debug (images 12-20): includes pins for serial programming and required elements for hardware boot and reset buttons on the board
Image 12
Image 12
Image 13
Image 13
Image 14
Image 14
Image 15
Image 15
Image 16
Image 16
Image 17
Image 17
Image 18
Image 18
Image 19
Image 19
Image 20
Image 20
  • Release (images 21-27): has only serial programming (with external Vcc/Vss) and HWB/RST pins and is much smaller than debug version
Image 21
Image 21
Image 22
Image 22
Image 23
Image 23
Image 24
Image 24
Image 25
Image 25
Image 26
Image 26
Image 27
Image 27
Both are two-sided PCBs with minimum amount of vias and maximum wire thickness (0.4 mm).
Sizes (w/o pins, enclosure and USB connector):

  1. Debug: 60x30x8 mm.
  2. Release: 40x25x8 mm.
Enclosure for release version is not ready yet, but I'm working on it, also as soon as possible I will present another – more compact – PCB design.





Programming
Programming should be performed in a several steps:
  1. Connect Keyring to FT232RL serial programmer.
  2. Upload new bootloader which supports 16 MHz quartz using avrdude to Keyring.
  3. Upload new fuses values to enable 16MHz support.
  4. Disconnect serial programmer.
  5. Connect Keyring to PC via USB.
  6. Enter DFU bootloader: Press RST and HWB buttons, then release RST button and finally release HWB button.
  7. Upload Keyring Firmware (Firmware/Keyring.hex) using FLIP software.
  8. Reset device (plug out and plug in it again or press RST button).
Steps 2-3 can be easily performed by executing Hardware/Fuses/Fuses.sh bash script, required bootloader is already there.
After first upload device will auto-format itself and will not be visible for a few seconds.
Its USB vendor ID and device ID are 0x03eb:0x204f, which corresponds to “LUFA Generic HID Demo Application”.






Installation
Currently Keyring Software has been tested only under Linux (Ubuntu/Mint), the next version will support Microsoft Windows.
To use Keyring Software you should prepare appropriate environment:

  1. Install Python.
  2. Install Qt and PyQt.
  3. Install PyUSB library.
  4. Copy rules.d/81-owlsan-keyring.rules permissions file to /etc/udev/rules.d/ in order to have non-root access to Keyring.
To run Keyring Software just execute Software/Keyring.py with Python. Keep in mind that default master password is “OWLSANKEYRING” (uppercase, w/o quotes).
Also please be notified that Keyring software is rather raw yet.






License
  1. OWLSAN Keyring Hardware is licensed under Creative Commons Attribution-ShareAlike 3.0 Unported License, refer to corresponding LICENSE.txt file or proceed via the link for more information: http://creativecommons.org/licenses/by-sa/3.0/
  2. OWLSAN Keyring Firmware is licensed under GNU GPLv3, refer to corresponding LICENSE.txt file or proceed via the link for more information: https://gnu.org/licenses/gpl.html
  3. OWLSAN Keyring Software is licensed under GNU GPLv3, refer to corresponding LICENSE.txt file or proceed via the link for more information: https://gnu.org/licenses/gpl.html





Downloads
The packages below contain all data related to this project: circuits, PCB schematics, bills of materials, firmware and software source codes and some required software.
And here you may get AVRDUDE (Linux 32/64) with FT232RL serial bitbang programming mode support:
Specifications:





Links
  1. Atmel AT90USB162 product page
  2. Microchip 24LC512 product page
  3. Atmel AT90USB162 DFU bootloader
  4. Atmel AT90USB162 DFU bootloader discuss on AVR Freaks
  5. FLIP utility page
  6. AVRDUDE home
  7. Adafruit Eagle Library (very useful!) at github
  8. PyQt page
  9. PyUSB page