Post on 20-Aug-2018
1
USB Programmer for AVR Controller
Minor Project Report
Submitted in the partial fulfillment of the requirements for the degree
of
Bachelor in Technology
By
Hitesh Sharma Manish Gandhi (05BEC107) (05BEC111)
Under the guidance of
Mr. V.G. Savani
Department of Electrical Engineering
Electronics & Communication Engineering Branch
Institute of Technology
Ahmedabad 382481
July 2008
2
CERTIFICATE
Department of Electrical Engineering
Electronics & Communication Engineering Branch
Institute of Technology
Ahmedabad 382481
This is to certify that following students of semester – VII B.Tech (Electronics and
Communication Engineering) have successfully completed their project work titled,
“USB Programmer for AVR Controller” satisfactorily in the partial fulfillment of
Minor Project for the Bachelors degree in Electronics & Communication of Nirma
University, Ahmedabad for the year 2008-2009.
Sr.No. Name of Student Roll No.
1. Hitesh Sharma 05BEC107
2. Manish Gandhi 05BEC111
Project Guide Sectional Head
Mr. V.G. Savani Prof. A. S. Ranade
HOD(EE)
Nirma University
3
ACKNOWLEDGEMENTS
We would like to express our gratitude to our guide Mr. Vijay Savani for providing us all
the required help & guidance. We are also thankful to Mr.H.Williams for sharing his
views on USB.
We are also thankful to Embedded Systems Academy (esacademy.com), San Jose,
USA, for allowing us to gain complete access to USB database. Finally we would like to
thank MCS electronics for Providing BascomAVR, Atmel for providing AVR Studio4.
4
ABSTRACT
The AVR USB Programmer has been carefully engineered and tested to provide superior
performance. This device is specially designed to work with Laptops/Notebooks
which doesn’t have Parallel or serial port. At full clock speed of 16 MHz of the
microcontroller it can program the flash at very high speeds in STK500 mode. This
programmer is supported in STK500 as well as Human Interface Device (HID) mode. It
is supported on all versions of Windows, including Windows Vista, as well as on Linux.
5
INDEX
Chapter
No.
Title Page
No.
Acknowledgement
iii
Abstract
iv
Index
v
List of Figures
7
1 Introduction
1.1
Brief Summary
8
1.2
Block Diagram
8
1.3
Features 9
1.4 Device Supported 9
2
USB Fundamentals
2.1 Introduction 10
2.2 USB Connectors 11
2.3 USB Protocols 12
3
In system Programming
3.1 Introduction 16
3.2 The Programming Interface 17
3.3 Programming operation 17
6
4
Project Circuit Diagram And Code
4.1 Schematic 19
4.2 PCB Layout 19
4.3 Code 20
5
Conclusion
33
6
Project Cost & Acronyms
34
7
References
35
7
LIST OF FIGURES
IMAGE PAGE NO.
Block Diagram
8
Device supported
9
Host and Target Device
10
USB connectors
11
In System Programming
16
MISO MOSI
17
Circuit Diagram
19
PCB
19
8
INTRODUCTION 1.1 Brief Summary
Programming of AVR controllers require parallel or serial port in general which is not
available with laptops. We have made a USB programmer which can program a series of
AVR microcontrollers to solve the above mentioned problem because USB is available
with all modern laptops and personal computers. Programming is done by the AVR
microcontroller which is a 8bit microcontroller with RICS architecture.
It has very powerful instruction set architecture and also a great features which make it
easier to work with this series of microcontroller by ATMEL.The Master Controller takes
input from the USB convert it into the serial format which is finally used to program our
target device which is again a AVR controller.
There is one more added advantage is that we do not need external power supply for both
the USB programmer as well as for the target device.
The block diagram is given below.
1.2 Block Diagram
Fig [1]
9
1.3 Features
• Compatible to Atmel's STK500V2 with implemented USB to Serial converter.
• Compatible with AVR Studio, AVRDUDE and compilers having support for
SKT500v2 protocol.
• Supports 2 modes, STK500 and USB-HID for compatibility.
• Adjustable ISP clock allows flashing of devices clocked at very low rate, e.g. 32
kHz.
• High Speed Programming: Programs 32 KB flash in just 15 seconds at full speed
of microcontroller.
• ISP clock can be lowered with a jumper (if the programmer software does
not support setting the ISP clock)
• Second USB to Serial converter for processing debug output from the target.
• Uses USB power supply, no external supply required.
• Supported on Windows 98, XP, Vista and Linux.
1.4 Devices Supported
Fig [2]
10
2. USB Fundamentals
2.1 Introduction
Universal Serial Bus (USB) is a serial bus standard to interface devices to a host
computer. USB was designed to allow many peripherals to be connected using a single
standardized interface socket and to improve the plug-and-play capabilities by allowing
hot swapping, that is, by allowing devices to be connected and disconnected without
rebooting the computer or turning off the device. Other convenient features include
providing power to low-consumption devices without the need for an external power
supply and allowing many devices to be used without requiring manufacturer specific,
individual device drivers to be installed.
USB is intended to replace many legacy varieties of serial and parallel ports. USB can
connect computer peripherals such as mouse, keyboards, PDAs, gamepads and joysticks,
scanners, digital cameras, printers, personal media players, and flash drives. For many of
those devices USB has become the standard connection method. USB was originally
designed for personal computers, but it has become commonplace on other devices such
as PDAs and video game consoles, and as a bridging power cord between a device and an
AC adapter plugged into a wall plug for charging purposes.
A USB system has an asymmetric design, consisting of a host, a multitude of downstream
USB ports, and multiple peripheral devices connected in a tiered-star topology.
Additional USB hubs may be included in the tiers, allowing branching into a tree
structure with up to five tier levels. A USB host may have multiple host controllers and
each host controller may provide one or more USB ports. Up to 127 devices, including
the hub devices may be connected to a single host controller.
Fig [3]
USB devices are linked in series through hubs. There always exists one hub known as the
root hub, which is built-in to the host controller. So-called "sharing hubs", which allow
11
multiple computers to access the same peripheral device(s), also exist and work by
switching access between PCs, either automatically or manually. They are popular in
small-office environments. In network terms, they converge rather than diverge branches.
USB device communication is based on pipes (logical channels). Pipes are connections
from the host controller to a logical entity on the device named an endpoint. The term
endpoint is also occasionally used to refer to the pipe. A USB device can have up to 32
active pipes, 16 into the host controller and 16 out of the controller. Each endpoint can
transfer data in one direction only, either into or out of the device, so each pipe is uni-
directional. Endpoints are grouped into interfaces and each interface is associated with a
single device function. An exception to this is endpoint zero, which is used for device
configuration and which is not associated with any interface.
When a new USB device is connected to a USB host, the USB device enumeration
process is started. The enumeration process first sends a reset signal to the USB device.
The speed of the USB device is determined during the reset signaling. After reset, USB
device setup information is read from the device by the host and the device is assigned a
unique host-controller-specific 7-bit address. If the device is supported by the host, the
device drivers needed for communicating with the device are loaded and the device is set
to configured state. If the USB host is restarted, the enumeration process is repeated for
all connected devices.
The host controller polls the bus for traffic, usually in a Round-robin fashion, so no USB
device can transfer any data on the bus without an explicit request from the host
controller.
2.2 USB Connectors
All devices have an upstream connection to the host and all hosts have a downstream
connection to the device. Upstream and downstream connectors are not mechanically
interchangeable, thus eliminating illegal loopback connections at hubs such as a
downstream port connected to a downstream port. There are commonly two types of
connectors, called type A and type B which are shown below.
Type A USB Connector Type B USB Connector
Pin Number Cable Colour Function
1 Red VBUS (5 volts)
2 White D-
3 Green D+
4 Black Ground
Fig [4]
12
Type A plugs always face upstream. Type A sockets will typically find themselves on
hosts and hubs. For example type A sockets are common on computer main boards and
hubs. Type B plugs are always connected downstream and consequently type B sockets
are found on devices. It is interesting to find type A to type A cables wired straight
through and an array of USB gender changers in some computer stores. This is in
contradiction of the USB specification. The only type A plug to type A plug devices are
bridges which are used to connect two computers together. Other prohibited cables are
USB extensions which has a plug on one end (either type A or type B) and a socket on
the other. These cables violate the cable length requirements of USB
2.3USB Protocols
Unlike RS-232 and similar serial interfaces where the format of data being sent is not
defined, USB is made up of several layers of protocols. While this sounds complicated,
don’t give up now. Once you understand what is going on, you really only have to worry
about the higher level layers. In fact most USB controller I.C.s will take care of the lower
layer, thus making it almost invisible to the end designer.
Each USB transaction consists of a
o Token Packet (Header defining what it expects to follow).
o Optional Data Packet, (Containing the payload) and a
o Status Packet (Used to acknowledge transactions and to provide a means
of error correction)
As we have already discussed, USB is a host centric bus. The host initiates all
transactions. The first packet, also called a token is generated by the host to describe what
is to follow and whether the data transaction will be a read or write and what the device’s
address and designated endpoint is. The next packet is generally a data packet carrying
the payload and is followed by a handshaking packet, reporting if the data or token was
received successfully, or if the endpoint is stalled or not available to accept data.
Common USB Packet Fields
Data on the USB is transmitted LSB bit first. USB packets consist of the following fields,
o Sync
All packets must start with a sync field. The sync field is 8 bits long at low
and full speed or 32 bits long for high speed and is used to synchronise the
clock of the receiver with that of the transmitter. The last two bits indicate
where the PID fields starts.
13
o PID
PID stands for Packet ID. This field is used to identify the type of packet
that is being sent. The following table shows the possible values.
Group PID
Value
Packet Identifier
0001 OUT Token
1001 IN Token
0101 SOF Token
Token
1101 SETUP Token
0011 DATA0
1011 DATA1
0111 DATA2
Data
1111 MDATA
0010 ACK Handshake
1010 NAK Handshake
1110 STALL Handshake
Handshake
0110 NYET (No Response
Yet)
1100 PREamble
1100 ERR
1000 Split
Special
0100 Ping
There are 4 bits to the PID, however to insure it is received correctly, the 4
bits are complemented and repeated, making an 8 bit PID in total. The
resulting format is shown below.
PID0 PID1 PID2 PID3 nPID0 nPID1 nPID2 nPID3
14
o ADDR
The address field specifies which device the packet is designated for.
Being 7 bits in length allows for 127 devices to be supported. Address 0 is
not valid, as any device which is not yet assigned an address must respond
to packets sent to address zero.
o ENDP
The endpoint field is made up of 4 bits, allowing 16 possible endpoints.
Low speed devices, however can only have 2 additional endpoints on top
of the default pipe. (4 endpoints max)
o CRC
Cyclic Redundancy Checks are performed on the data within the packet
payload. All token packets have a 5 bit CRC while data packets have a 16
bit CRC.
o EOP
End of packet. Signaled by a Single Ended Zero (SE0) for approximately
2 bit times followed by a J for 1 bit time.
USB Packet Types
USB has four different packet types. Token packets indicate the type of transaction to
follow, data packets contain the payload, handshake packets are used for acknowledging
data or reporting errors and start of frame packets indicate the start of a new frame.
o Token Packets
There are three types of token packets,
� In - Informs the USB device that the host wishes to read
information.
� Out - Informs the USB device that the host wishes to send
information.
� Setup - Used to begin control transfers.
Token Packets must conform to the following format.
Sync PID ADDR ENDP CRC5 EOP
15
o Data Packets
There are two types of data packets each capable of transmitting up to
1024 bytes of data.
� Data0
� Data1
High Speed mode defines another two data PIDs, DATA2 and MDATA.
Data packets have the following format.
Sync PID Data CRC16 EOP
� Maximum data payload size for low-speed devices is 8 bytes.
� Maximum data payload size for full-speed devices is 1023 bytes.
� Maximum data payload size for high-speed devices is 1024 bytes.
� Data must be sent in multiples of bytes.
o Handshake Packets
There are three type of handshake packets which consist simply of the PID
� ACK - Acknowledgment that the packet has been successfully
received.
� NAK - Reports that the device temporary cannot send or received
data. Also used during interrupt transactions to inform the host
there is no data to send.
� STALL - The device finds its in a state that it requires intervention
from the host.
Handshake Packets have the following format.
Sync PID EOP
o Start of Frame Packets
The SOF packet consisting of an 11-bit frame number is sent by the host
every 1ms ± 500ns on a full speed bus or every 125 µs ± 0.0625 µs on a
high speed bus.
Sync PID Frame
Number CRC5 EOP
16
3. In system Programming
3.1 Introduction
In-System Programming allows programming and reprogramming of any AVR
microcontroller positioned inside the end system. Using a simple Three-wire SPI
interface, the In-System Programmer communicates serially with the AVR
microcontroller, In-System Programming eliminates the physical removal of chips from
the system. This will save time, and money, both during development in the lab, and
when updating the software or parameters in the field.
3.2 The Programming Interface
For In-System Programming, the programmer is connected to the target using as few
Wires as possible. To program any AVR microcontroller in any target system, a simple
Six-wire interface is used to connect the programmer to the target PCB. Figure
Below shows the connections needed. The Serial Peripheral Interface (SPI) consists of
three wires: Serial Clock (SCK), MasterIn – Slave Out (MISO) and Master Out – Slave
In (MOSI).When programming theAVR, the In-System Programmer always operate as
the Master, and the target system always operate as the Slave.
Fig [5]
The In-System Programmer (Master) provides the clock for the communication on the
SCK Line. Each pulse on the SCK Line transfers one bit from the Programmer (Master)
to the Target (Slave) on the Master Out – Slave In (MOSI) line. Simultaneously,
each pulse on the SCK Line transfers one bit from the target (Slave) to the Programmer
(Master) on the Master In – Slave Out (MISO) line.
To assure proper communication on the three SPI lines, it is necessary to connect ground
on the programmer to ground on the target (GND).The In-System Programmer and target
system need to operate with the same reference voltage. This is done by connecting
ground of the target to ground of the programmer.
17
3.3 Programming operation
Fig [6]
• GND: The In-System Programmer and target system need to operate with the same
reference voltage. This is done by connecting ground of the target to ground of the
programmer. No special considerations apply to this pin.
• RESET: The target AVR microcontroller will enter Serial Programming mode only
when its reset line is active (low).To simplify this operation, it is recommended that
the target reset can be controlled by the In-System Programmer. Immediately after
Reset has gone active, the In-System Programmer will start to communicate on the
three dedicated SPI wires SCK, MISO, and MOSI.
18
• SCK: When programming the AVR in Serial mode, the In-System Programmer
supplies clock information on the SCK pin. This pin is always driven by the
programmer, and the target system should never attempt to drive this wire when
target reset is active. Immediately after the Reset goes active, this pin will be
driven to zero by the programmer. During this first phase of the programming
Cycle, keeping the SCK Line free from pulses is critical, as pulses will cause the
target AVR to loose synchronization with the programmer.
• MOSI :When programming the AVR in Serial mode, the In-System Programmer
supplies data to the target on the MOSI pin. This pin is always driven by the
programmer, and the target system should never attempt to drive this wire when
target reset is active. The target AVR microcontroller will always set up its MOSI
pin to be an input with no pull up whenever Reset is active. See also the
description of the Reset wire.
• MISO: When Reset is applied to the target AVR microcontroller, the MISO pin is
set up to be an input with no pull up. Only after the “Programming Enable”
command has been correctly transmitted to the target will the target AVR
microcontroller set its MISO pin to become an output. During this first time, the
In-System programmer will apply its pull up to keep the MISO line stable until it
is driven by the target microcontroller.
• VCC: When programming the target microcontroller, the programmer outputs
need to stay within the ranges specified in the DC Characteristics. To easily adapt
to any target voltage, the programmer can draw all power required from the target
system. This is allowed as the In-System Programmer will draw very little power
from the target system, typically no more than 20 mA.
19
4. Project Circuit Diagram and Code
4.1 Circuit Diagram
Fig [7]
4.2 PCB Layout
Fig [8]
20
4.3 Code /*
General Description:
This module implements hardware initialization and the USB interface
*/
#include "hardware.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/wdt.h>
#include <util/delay.h>
#include <string.h>
#include "utils.h"
#include "usbdrv.h"
#include "oddebug.h"
#include "stk500protocol.h"
#include "vreg.h"
#include "serial.h"
#include "timer.h"
/* --------------------------------------------------------------------
----- */
/* CDC class requests: */
enum {
SEND_ENCAPSULATED_COMMAND = 0,
GET_ENCAPSULATED_RESPONSE,
SET_COMM_FEATURE,
GET_COMM_FEATURE,
CLEAR_COMM_FEATURE,
SET_LINE_CODING = 0x20,
GET_LINE_CODING,
SET_CONTROL_LINE_STATE,
SEND_BREAK
};
/* defines for 'requestType' */
#define REQUEST_TYPE_LINE_CODING 0 /* CDC GET/SET_LINE_CODING */
#define REQUEST_TYPE_HID_FIRST 1 /* first block of HID reporting
*/
#define REQUEST_TYPE_HID_SUBSEQUENT 2 /* subsequent block of HID
reporting */
#define REQUEST_TYPE_HID_DEBUGDATA 3 /* read/write data from/to
debug interface */
#define REQUEST_TYPE_VENDOR 4 /* vendor request for get/set
debug data */
/* --------------------------------------------------------------------
----- */
#if ENABLE_CDC_INTERFACE
static uchar modeBuffer[7] = {0x80, 0x25, 0, 0, 0, 0, 8}; /*
default: 9600 bps, 8n1 */
# if USE_DCD_REPORTING
static uchar intr3Status;
21
# endif
#endif
#if ENABLE_HID_INTERFACE
static uchar hidStatus;
#endif
static uchar requestType;
static uchar useHIDInterface;
#if ENABLE_CDC_INTERFACE
static PROGMEM char deviceDescrCDC[] = { /* USB device descriptor */
18, /* sizeof(usbDescriptorDevice): length of descriptor in
bytes */
USBDESCR_DEVICE, /* descriptor type */
0x10, 0x01, /* USB version supported */
0x02, /* device class: CDC */
0, /* subclass */
0, /* protocol */
8, /* max packet size */
USB_CFG_VENDOR_ID, /* 2 bytes */
0xe1, 0x05, /* 2 bytes: shared PID for CDC-ACM devices
*/
USB_CFG_DEVICE_VERSION, /* 2 bytes */
1, /* manufacturer string index */
2, /* product string index */
3, /* serial number string index */
1, /* number of configurations */
};
static PROGMEM char configDescrCDC[] = { /* USB configuration
descriptor */
9, /* sizeof(usbDescriptorConfiguration): length of
descriptor in bytes */
USBDESCR_CONFIG, /* descriptor type */
67, 0, /* total length of data returned (including inlined
descriptors) */
2, /* number of interfaces in this configuration */
1, /* index of this configuration */
0, /* configuration name string index */
#if USB_CFG_IS_SELF_POWERED
USBATTR_SELFPOWER, /* attributes */
#else
USBATTR_BUSPOWER, /* attributes */
#endif
USB_CFG_MAX_BUS_POWER/2, /* max USB current in 2mA units
*/
/* interface descriptors follow inline: */
/* Interface Descriptor for CDC-ACM Control */
9, /* sizeof(usbDescrInterface): length of descriptor in
bytes */
USBDESCR_INTERFACE, /* descriptor type */
0, /* index of this interface */
0, /* alternate setting for this interface */
1, /* endpoints excl 0: number of endpoint descriptors to
follow */
USB_CFG_INTERFACE_CLASS, /* see usbconfig.h */
USB_CFG_INTERFACE_SUBCLASS,
USB_CFG_INTERFACE_PROTOCOL,
0, /* string index for interface */
22
/* CDC Class-Specific descriptors */
5, /* sizeof(usbDescrCDC_HeaderFn): length of descriptor
in bytes */
0x24, /* descriptor type */
0, /* Subtype: header functional descriptor */
0x10, 0x01, /* CDC spec release number in BCD */
4, /* sizeof(usbDescrCDC_AcmFn): length of descriptor in
bytes */
0x24, /* descriptor type */
2, /* Subtype: abstract control management functional
descriptor */
0x02, /* capabilities: SET_LINE_CODING, GET_LINE_CODING,
SET_CONTROL_LINE_STATE */
5, /* sizeof(usbDescrCDC_UnionFn): length of descriptor in
bytes */
0x24, /* descriptor type */
6, /* Subtype: union functional descriptor */
0, /* CDC_COMM_INTF_ID: master interface (control) */
1, /* CDC_DATA_INTF_ID: slave interface (data) */
5, /* sizeof(usbDescrCDC_CallMgtFn): length of descriptor
in bytes */
0x24, /* descriptor type */
1, /* Subtype: call management functional descriptor */
0x03, /* capabilities: allows management on data interface,
handles call management by itself */
1, /* CDC_DATA_INTF_ID: interface used for call management
*/
/* Endpoint Descriptor */
7, /* sizeof(usbDescrEndpoint) */
USBDESCR_ENDPOINT, /* descriptor type = endpoint */
0x83, /* IN endpoint number 3 */
0x03, /* attrib: Interrupt endpoint */
8, 0, /* maximum packet size */
100, /* in ms */
/* Interface Descriptor for CDC-ACM Data */
9, /* sizeof(usbDescrInterface): length of descriptor in
bytes */
USBDESCR_INTERFACE, /* descriptor type */
1, /* index of this interface */
0, /* alternate setting for this interface */
2, /* endpoints excl 0: number of endpoint descriptors to
follow */
0x0a, /* Data Interface Class Codes */
0, /* interface subclass */
0, /* Data Interface Class Protocol Codes */
0, /* string index for interface */
/* Endpoint Descriptor */
7, /* sizeof(usbDescrEndpoint) */
USBDESCR_ENDPOINT, /* descriptor type = endpoint */
0x01, /* OUT endpoint number 1 */
0x02, /* attrib: Bulk endpoint */
HW_CDC_PACKET_SIZE, 0, /* maximum packet size */
23
0, /* in ms */
/* Endpoint Descriptor */
7, /* sizeof(usbDescrEndpoint) */
USBDESCR_ENDPOINT, /* descriptor type = endpoint */
0x81, /* IN endpoint number 1 */
0x02, /* attrib: Bulk endpoint */
HW_CDC_PACKET_SIZE, 0, /* maximum packet size */
0, /* in ms */
};
#endif /* ENABLE_CDC_INTERFACE */
#if ENABLE_HID_INTERFACE
static PROGMEM char deviceDescrHID[] = { /* USB device descriptor */
18, /* sizeof(usbDescriptorDevice): length of descriptor in
bytes */
USBDESCR_DEVICE, /* descriptor type */
0x01, 0x01, /* USB version supported */
0, /* device class: composite */
0, /* subclass */
0, /* protocol */
8, /* max packet size */
USB_CFG_VENDOR_ID, /* 2 bytes */
0xdf, 0x05, /* 2 bytes: shared PID for HIDs */
USB_CFG_DEVICE_VERSION, /* 2 bytes */
1, /* manufacturer string index */
2, /* product string index */
0, /* serial number string index */
1, /* number of configurations */
};
static PROGMEM char configDescrHID[] = { /* USB configuration
descriptor */
9, /* sizeof(usbDescriptorConfiguration): length of
descriptor in bytes */
USBDESCR_CONFIG,/* descriptor type */
18 + 7 + 9, 0, /* total length of data returned (including inlined
descriptors) */
1, /* number of interfaces in this configuration */
1, /* index of this configuration */
0, /* configuration name string index */
#if USB_CFG_IS_SELF_POWERED
USBATTR_SELFPOWER, /* attributes */
#else
USBATTR_BUSPOWER, /* attributes */
#endif
USB_CFG_MAX_BUS_POWER/2, /* max USB current in 2mA units */
/* interface descriptor follows inline: */
9, /* sizeof(usbDescrInterface): length of descriptor in
bytes */
USBDESCR_INTERFACE, /* descriptor type */
0, /* index of this interface */
0, /* alternate setting for this interface */
USB_CFG_HAVE_INTRIN_ENDPOINT, /* endpoints excl 0: number of
endpoint descriptors to follow */
3, /* interface class: HID */
0, /* subclass */
0, /* protocol */
24
0, /* string index for interface */
9, /* sizeof(usbDescrHID): length of descriptor in bytes
*/
USBDESCR_HID, /* descriptor type: HID */
0x01, 0x01, /* BCD representation of HID version */
0x00, /* target country code */
0x01, /* number of HID Report (or other HID class) Descriptor
infos to follow */
0x22, /* descriptor type: report */
USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH, 0, /* total length of report
descriptor */
7, /* sizeof(usbDescrEndpoint) */
USBDESCR_ENDPOINT, /* descriptor type = endpoint */
0x81, /* IN endpoint number 1 */
0x03, /* attrib: Interrupt endpoint */
8, 0, /* maximum packet size */
USB_CFG_INTR_POLL_INTERVAL, /* in ms */
};
PROGMEM char usbDescriptorHidReport[60] = {
0x06, 0x00, 0xff, // USAGE_PAGE (Generic Desktop)
0x09, 0x01, // USAGE (Vendor Usage 1)
0xa1, 0x01, // COLLECTION (Application)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
0x75, 0x08, // REPORT_SIZE (8)
0x85, 0x01, // REPORT_ID (1)
0x95, 0x0e, // REPORT_COUNT (14)
0x09, 0x00, // USAGE (Undefined)
0xb2, 0x02, 0x01, // FEATURE (Data,Var,Abs,Buf)
0x85, 0x02, // REPORT_ID (2)
0x95, 0x1e, // REPORT_COUNT (30)
0x09, 0x00, // USAGE (Undefined)
0xb2, 0x02, 0x01, // FEATURE (Data,Var,Abs,Buf)
0x85, 0x03, // REPORT_ID (3)
0x95, 0x3e, // REPORT_COUNT (62)
0x09, 0x00, // USAGE (Undefined)
0xb2, 0x02, 0x01, // FEATURE (Data,Var,Abs,Buf)
0x85, 0x04, // REPORT_ID (4)
0x95, 0x7e, // REPORT_COUNT (126)
0x09, 0x00, // USAGE (Undefined)
0xb2, 0x02, 0x01, // FEATURE (Data,Var,Abs,Buf)
0x85, 0x06, // REPORT_ID (5) [for debug
interface]
0x95, 0x3e, // REPORT_COUNT (62)
0x09, 0x00, // USAGE (Undefined)
0xb2, 0x02, 0x01, // FEATURE (Data,Var,Abs,Buf)
0xc0 // END_COLLECTION
};
/* Note: REPORT_COUNT does not include report-ID byte */
25
#endif /* ENABLE_HID_INTERFACE */
/* --------------------------------------------------------------------
----- */
uchar usbFunctionDescriptor(usbRequest_t *rq)
{
uchar *p = NULL, len = 0, useHID = useHIDInterface;
if(useHID){
#if ENABLE_HID_INTERFACE
if(rq->wValue.bytes[1] == USBDESCR_DEVICE){
p = (uchar *)deviceDescrHID;
len = sizeof(deviceDescrHID);
}else if(rq->wValue.bytes[1] == USBDESCR_CONFIG){
p = (uchar *)configDescrHID;
len = sizeof(configDescrHID);
}else{ /* must be HID descriptor */
p = (uchar *)(configDescrHID + 18);
len = 9;
}
#endif
}else{
#if ENABLE_CDC_INTERFACE
if(rq->wValue.bytes[1] == USBDESCR_DEVICE){
p = (uchar *)deviceDescrCDC;
len = sizeof(deviceDescrCDC);
}else{ /* must be config descriptor */
p = (uchar *)configDescrCDC;
len = sizeof(configDescrCDC);
}
#endif
}
usbMsgPtr = p;
return len;
}
/* --------------------------------------------------------------------
----- */
/* ----------------------------- USB interface ------------------------
----- */
/* --------------------------------------------------------------------
----- */
uchar usbFunctionSetup(uchar data[8])
{
usbRequest_t *rq = (void *)data;
uchar rqType = rq->bmRequestType & USBRQ_TYPE_MASK;
if(rqType == USBRQ_TYPE_CLASS){ /* class request type */
if(useHIDInterface){
#if ENABLE_HID_INTERFACE
if(rq->bRequest == USBRQ_HID_GET_REPORT || rq->bRequest ==
USBRQ_HID_SET_REPORT){
hidStatus = rq->wValue.bytes[0]; /* store report ID
*/
if(rq->wValue.bytes[0] == 5){ /* report ID */
requestType = REQUEST_TYPE_HID_DEBUGDATA;
26
}else{
requestType = REQUEST_TYPE_HID_FIRST;
}
/* the driver counts the total number of bytes for us
*/
return 0xff;
}
#endif
}else{
#if ENABLE_CDC_INTERFACE
if(rq->bRequest == GET_LINE_CODING || rq->bRequest ==
SET_LINE_CODING){
requestType = REQUEST_TYPE_LINE_CODING;
return 0xff;
}
# if USE_DCD_REPORTING
if(rq->bRequest == SET_CONTROL_LINE_STATE){
/* Report serial state (carrier detect). On several
Unix platforms,
* tty devices can only be opened when carrier detect
is set.
*/
intr3Status = 2;
}
# endif
#endif
}
}
#if ENABLE_DEBUG_INTERFACE
else if(rqType == USBRQ_TYPE_VENDOR){ /* vendor requests */
if(rq->bRequest == 1){ /* transmit data */
serialPutc(rq->wValue.bytes[0]);
}else if(rq->bRequest == 2){
requestType = REQUEST_TYPE_VENDOR;
return 0xff; /* handle in usbFunctionRead() */
}
}
#endif
return 0;
}
uchar usbFunctionRead(uchar *data, uchar len)
{
if(requestType == REQUEST_TYPE_LINE_CODING){
#if ENABLE_CDC_INTERFACE
/* return the "virtual" configuration */
memcpy(data, modeBuffer, 7);
return 7;
#endif
}
#if ENABLE_DEBUG_INTERFACE
else if(requestType == REQUEST_TYPE_VENDOR){
uchar cnt;
for(cnt = 0; cnt < len && ringBufferHasData(&serialRingBuffer);
cnt++){
*data++ = ringBufferRead(&serialRingBuffer);
}
return cnt;
#if ENABLE_HID_INTERFACE
27
}else if(requestType == REQUEST_TYPE_HID_DEBUGDATA){
uchar *p = data, remaining;
if(hidStatus == 5){ /* first call */
*p++ = hidStatus; /* report ID */
*p++ = ringBufferCount(&serialRingBuffer);
remaining = len - 2;
hidStatus = 1; /* continue with subsequent call */
}else{
remaining = len;
}
if(hidStatus){
do{
if(!ringBufferHasData(&serialRingBuffer)){
hidStatus = 0;
break;
}
*p++ = ringBufferRead(&serialRingBuffer);
}while(--remaining);
}
return len;
#endif
}
#endif
#if ENABLE_HID_INTERFACE
else if(requestType == REQUEST_TYPE_HID_FIRST || requestType ==
REQUEST_TYPE_HID_SUBSEQUENT){
uchar *p = data, remaining;
if(requestType == REQUEST_TYPE_HID_FIRST){
int cnt;
*p++ = hidStatus; /* report ID */
cnt = stkGetTxCount();
if(utilHi8(cnt)){
*p = 255;
}else{
*p = cnt; /* second byte is number of remaining
bytes buffered */
}
p++;
remaining = len - 2;
requestType = REQUEST_TYPE_HID_SUBSEQUENT;
}else{
remaining = len;
}
if(hidStatus){
do{
int c = stkGetTxByte();
if(c < 0){
hidStatus = 0;
break;
}
*p++ = c;
}while(--remaining);
}
return len;
}
#endif
return 0; /* error -> terminate transfer */
}
28
uchar usbFunctionWrite(uchar *data, uchar len)
{
if(requestType == REQUEST_TYPE_LINE_CODING){
#if ENABLE_CDC_INTERFACE
/* Don't know why data toggling is reset when line coding is
changed, but it is... */
USB_SET_DATATOKEN1(USBPID_DATA1); /* enforce DATA0 token for
next transfer */
/* store the line configuration so that we can return it on
request */
memcpy(modeBuffer, data, 7);
return 1;
#endif
}
#if ENABLE_HID_INTERFACE
#if ENABLE_DEBUG_INTERFACE
else if(requestType == REQUEST_TYPE_HID_DEBUGDATA){
uchar *p = data, rval = len != 8;
if(hidStatus == 5){ /* first call */
hidStatus = -p[1]; /* second byte is data length */
p += 2;
len -= 2;
}
do{
if(!hidStatus)
break;
serialPutc(*p++);
hidStatus++;
}while(--len);
return rval; /* the last packet must have 7 bytes insted of
8 */
}
#endif
else if(requestType == REQUEST_TYPE_HID_FIRST || requestType ==
REQUEST_TYPE_HID_SUBSEQUENT){
uchar *p = data, rval = len != 8;
if(requestType == REQUEST_TYPE_HID_FIRST){
hidStatus = p[1]; /* second byte is data length */
p += 2;
len -= 2;
requestType = REQUEST_TYPE_HID_SUBSEQUENT;
}
do{
if(!hidStatus)
break;
stkSetRxChar(*p++);
hidStatus--;
}while(--len);
return rval; /* the last packet must have 7 bytes insted of
8 */
}
#endif
return 1; /* error -> accept everything until end */
}
void usbFunctionWriteOut(uchar *data, uchar len)
{
#if ENABLE_CDC_INTERFACE
29
do{ /* len must be at least 1 character, the driver discards zero
sized packets */
stkSetRxChar(*data++);
}while(--len);
#endif
}
/* --------------------------------------------------------------------
----- */
/* --------------------------------------------------------------------
----- */
/* --------------------------------------------------------------------
----- */
static void readInterfaceType(void)
{
#if ENABLE_HID_INTERFACE && ENABLE_CDC_INTERFACE
#if METABOARD_HARDWARE
useHIDInterface = !PORT_PIN_VALUE(HWPIN_JUMPER); /* if jumper is
set -> HID mode */
#else
PORT_DDR_SET(HWPIN_ISP_MOSI);
PORT_PIN_SET(HWPIN_ISP_MOSI);
PORT_DDR_CLR(HWPIN_ISP_MOSI);
PORT_PIN_CLR(HWPIN_ISP_MOSI); /* deactivate pullup */
useHIDInterface = PORT_PIN_VALUE(HWPIN_ISP_MOSI) == 0;
#endif /* METABOARD_HARDWARE */
#elif ENABLE_HID_INTERFACE
useHIDInterface = 1;
#elif !ENABLE_CDC_INTERFACE
#error "You must set either ENABLE_HID_INTERFACE or
ENABLE_CDC_INTERFACE in hardware.h!"
#endif
}
/*
20 pin HVSP / PP connector:
1 .... GND
2 .... Vtarget
3 .... HVSP SCI
4 .... RESET
16 ... HVSP SDO
18 ... HVSP SII
20 ... HVSP SDI
* Timer usage:
* Timer 0 [8 bit]:
* 1/64 prescaler for timer interrupt
* Timer 1 [16 bit]:
* PWM for voltage supply -> fastPWM mode
* f = 23.4 kHz -> prescaler = 1, 9 bit
* Timer 2 [8 bit]:
* Clock generation for target device
*/
static void hardwareInit(void)
{
uchar i;
uchar portB = 0, portC = 0, portD = 0, ddrB = 0, ddrC = 0, ddrD = 0;
30
#if ENABLE_HVPROG
UTIL_PBIT_SET(port, HWPIN_HVSP_SUPPLY);
UTIL_PBIT_SET(ddr, HWPIN_HVSP_SUPPLY);
UTIL_PBIT_CLR(port, HWPIN_SMPS_OUT);
UTIL_PBIT_SET(ddr, HWPIN_SMPS_OUT);
UTIL_PBIT_CLR(port, HWPIN_ADC_SMPS);
UTIL_PBIT_CLR(ddr, HWPIN_ADC_SMPS);
UTIL_PBIT_CLR(port, HWPIN_HVSP_HVRESET);
UTIL_PBIT_SET(ddr, HWPIN_HVSP_HVRESET);
UTIL_PBIT_CLR(port, HWPIN_HVSP_SCI);
UTIL_PBIT_SET(ddr, HWPIN_HVSP_SCI);
UTIL_PBIT_CLR(port, HWPIN_HVSP_SII);
UTIL_PBIT_SET(ddr, HWPIN_HVSP_SII);
UTIL_PBIT_CLR(port, HWPIN_HVSP_SDI);
UTIL_PBIT_SET(ddr, HWPIN_HVSP_SDI);
UTIL_PBIT_CLR(port, HWPIN_HVSP_SDO);
UTIL_PBIT_CLR(ddr, HWPIN_HVSP_SDO);
#endif /* ENABLE_HVPROG */
#ifdef HWPIN_ISP_CLK
UTIL_PBIT_CLR(port, HWPIN_ISP_CLK);
UTIL_PBIT_SET(ddr, HWPIN_ISP_CLK);
#endif
#if METABOARD_HARDWARE
UTIL_PBIT_SET(ddr, HWPIN_LED);
UTIL_PBIT_SET(port, HWPIN_LED);
/* keep all I/O pins and DDR bits for ISP on low level */
UTIL_PBIT_CLR(port, HWPIN_ISP_SUPPLY1);
UTIL_PBIT_CLR(port, HWPIN_ISP_SUPPLY2);
UTIL_PBIT_SET(ddr, HWPIN_ISP_SUPPLY1);
UTIL_PBIT_SET(ddr, HWPIN_ISP_SUPPLY2);
#else /* METABOARD_HARDWARE */
UTIL_PBIT_CLR(port, HWPIN_ISP_DRIVER);
UTIL_PBIT_SET(ddr, HWPIN_ISP_DRIVER);
UTIL_PBIT_SET(ddr, HWPIN_LED);
UTIL_PBIT_CLR(port, HWPIN_LED);
UTIL_PBIT_CLR(port, HWPIN_ADC_VTARGET);
UTIL_PBIT_CLR(ddr, HWPIN_ADC_VTARGET);
UTIL_PBIT_CLR(port, HWPIN_ISP_SCK);
UTIL_PBIT_SET(ddr, HWPIN_ISP_SCK);
UTIL_PBIT_SET(port, HWPIN_ISP_MISO);
UTIL_PBIT_CLR(ddr, HWPIN_ISP_MISO);
UTIL_PBIT_CLR(port, HWPIN_ISP_MOSI);
UTIL_PBIT_SET(ddr, HWPIN_ISP_MOSI);
UTIL_PBIT_CLR(port, HWPIN_ISP_RESET);
UTIL_PBIT_SET(ddr, HWPIN_ISP_RESET);
#endif /* METABOARD_HARDWARE */
UTIL_PBIT_SET(port, HWPIN_ISP_TXD);
UTIL_PBIT_SET(ddr, HWPIN_ISP_TXD);
UTIL_PBIT_SET(port, HWPIN_ISP_RXD);
UTIL_PBIT_CLR(ddr, HWPIN_ISP_RXD);
UTIL_PBIT_CLR(port, HWPIN_USB_DPLUS);
UTIL_PBIT_CLR(ddr, HWPIN_USB_DPLUS);
UTIL_PBIT_CLR(port, HWPIN_USB_DMINUS);
UTIL_PBIT_CLR(ddr, HWPIN_USB_DMINUS);
UTIL_PBIT_SET(port, HWPIN_JUMPER);
31
UTIL_PBIT_CLR(ddr, HWPIN_JUMPER);
PORTB = portB;
DDRB = ddrB;
PORTC = portC;
DDRC = ddrC;
PORTD = portD;
DDRD = ddrD;
usbDeviceDisconnect(); /* enforce re-enumeration, do this while
interrupts are disabled! */
i = 0;
while(--i){ /* fake USB disconnect for > 250 ms */
wdt_reset();
_delay_ms(1);
}
usbDeviceConnect();
/* timer 0 configuration: ~ 1.365 ms interrupt @ 12 MHz */
TCCR0 = 3; /* 1/64 prescaler */
TIMSK = (1 << TOIE0); /* enable timer0 overflow interrupt */
#if METABOARD_HARDWARE
/* timer 1 configuration (used for target clock): */
TCCR1A = UTIL_BIN8(1000, 0010); /* OC1A = PWM out, OC1B
disconnected */
TCCR1B = UTIL_BIN8(0001, 1001); /* wgm 14: TOP = ICR1, prescaler =
1 */
ICR1 = F_CPU / 1000000 - 1; /* TOP value for 1 MHz */
OCR1A = F_CPU / 2000000 - 1; /* 50% duty cycle */
#else /* METABOARD_HARDWARE */
/* timer 1 configuration (used for high voltage generator): ~23.4
kHz PWM (9 bit) */
TCCR1A = UTIL_BIN8(1000, 0010); /* OC1A = PWM, OC1B disconnected,
9 bit */
TCCR1B = UTIL_BIN8(0000, 1001); /* 9 bit, prescaler=1 */
OCR1A = 1; /* set duty cycle to minimum */
/* timer 2 configuration (used for target clock) */
#ifdef TCCR2A
TCCR2A = UTIL_BIN8(0000, 0010); /* OC2A disconnected, CTC mode (WGM
0,1) */
TCCR2B = UTIL_BIN8(0000, 0001); /* prescaler=1, CTC mode (WGM 2) */
#else
TCCR2 = UTIL_BIN8(0000, 1001); /* OC2 disconnected, prescaler=1,
CTC mode */
#endif
OCR2 = 2; /* should give 3 MHz clock */
#endif /* METABOARD_HARDWARE */
}
int main(void)
{
wdt_enable(WDTO_1S);
odDebugInit();
DBG1(0x00, 0, 0);
#if ENABLE_DEBUG_INTERFACE
serialInit();
#endif
readInterfaceType();
hardwareInit();
32
vregInit();
usbInit();
sei();
DBG1(0x01, 0, 0);
for(;;){ /* main event loop */
wdt_reset();
usbPoll();
stkPoll();
#if ENABLE_CDC_INTERFACE
if(!useHIDInterface && usbInterruptIsReady()){
static uchar sendEmptyFrame = 1,
buffer[HW_CDC_PACKET_SIZE];
/* start with empty frame because the host eats the first
packet -- don't know why... */
int c;
uchar i = 0;
while(i < HW_CDC_PACKET_SIZE && (c = stkGetTxByte()) >= 0){
buffer[i++] = c;
}
if(i > 0 || sendEmptyFrame){
sendEmptyFrame = i; /* send an empty block after
last data block to indicate transfer end */
usbSetInterrupt(buffer, i);
}
}
#endif
#if USE_DCD_REPORTING && ENABLE_CDC_INTERFACE
/* We need to report rx and tx carrier after open attempt */
if(intr3Status != 0 && usbInterruptIsReady3()){
static uchar serialStateNotification[8] = {0xa1, 0x20, 0,
0, 0, 0, 2, 0};
static uchar serialStateData[2] = {3, 0};
if(intr3Status == 2){
usbSetInterrupt3(serialStateNotification, 8);
}else{
usbSetInterrupt3(serialStateData, 2);
}
intr3Status--;
}
#endif
}
return 0;
}
33
CONCLUSION
This project provides a lucid solution for the electronics related to microcontrollers like
robotics. Its universal application makes it viable for different uses. The project also
provides on board power supply and turned out to be very economical compared to its
applications. The overall cost comes around Rs 550. The whole circuit can be fit into a
20square inch circuit board.
34
PROJECT COST
COMPONENT QUANTITY COST(RS.)
ATMEGA8 1 80
USB Cable 1 150
74HC126N Quad Buffer 1 50
12 MHz Crystal 1 20
28 pin IC socket 1 5
14 pin IC socket 1 5
Resistor Carbon Film 68 Ohm 1/4 Watt 10% 2 1
Resistor Carbon Film 270 Ohm 1/4 Watt 10% 1 1
Resistor Carbon Film 1K Ohm 1/4 Watt 10% 2 1
Resistor Carbon Film 10K Ohm 1/4 Watt 10% 5 1
Resistor Carbon Film 2K2 Ohm 1/4 Watt 10% 1 1
Resistor Carbon Film 22K Ohm 1/4 Watt 10% 1 1
Resistor Carbon Film 33K Ohm 1/4 Watt 10% 1 1
Ceramic Radial Capacitor 22pF 50V 5% 2 2
Ceramic Radial Capacitor .01uF 50V 10% 2 2
Electrolytic Radial Capacitor 4.7uF 16V 20% 1 2
3.6 Volt Low Power Zener Diode 2 10
5x2 Pin Gold Straight Header .100" 1 30
2 x 1 Pin Gold Straight Header .100" 3 3
PCB 1 175
Total 541
ACRONYMS
The following are the acronyms that are used in the report.
� USB – Universal Serial Bus.
� ACK – Acknowledge signal.
� NAK-Negative Acknowledge signal
� Sync– Synchronize.
� PID – Packet ID.
� ADDR– address.
� CRC – Cyclic Redundancy Checks.
� EOP – End of packet.
� MSB/LSB – Most/Least Significant Bit.
35
REFERENCES
[1].www.kamami.com
[2].www.Robokits.co.in
[3].www.wikkipedia.com
[4].www.beyondlogic.com
[5]. www.wikkipedia.com
[6].www.avrfreak.com
[7].Eagle Simulation