Pages

Saturday, July 28, 2012

LED Blinking Program

Here is a simple LED Blinking Program for beginners

#include

void delay(unsigned int i)
{
 unsigned int j;
 while(i-->0)
 for(j=0;j<500;j++);
}

void main()
{
P1=0x00;
 while(1)
 {
 P1=0x01;
 delay(1000);
 P1=0x00;
 delay(1000);
 }
} 

Friday, July 27, 2012

Thursday, July 26, 2012

DC Motor Interface with 8051 Microcontroller


A DC motor runs with the help of Direct Current. It produces torque by using both electricity and magnetic fields. The common term used to refer both fields is Electromagnetism. When a current carrying conductor is placedin the external magnetic field, then it will experience a force proportional to the current in the conductor and strength of the external magnetic field.
                        F = B*L*I
Where F is force in dynes.
            B is flux density in lines per square centimetres.
            L is length of the conductor
            I  is current in the conductor.

The same principle is used in the DC motor. The DC motor has rotor, stator, field magnet, brushes, shaft, commutator. The DC motor requires more current to produce initial torque than in running state.

Schematic

Code

#include
# define MOTOR P0

void delay(unsigned int);

void main()
{
    while(1)
    {
     MOTOR=0X01;
     delay(20);
     MOTOR=0X02;
     delay(20);
     MOTOR2=0X0A;
     delay(20);
     MOTOR2=0X08;
     delay(20);
    }




with this code u can control two motors in clockwise as well as counter clockwise...

Graphical LCD interfacing with pic controller

Here is a sample code to Interface Graphical LCD to a PIC Controller


CODE

#define                KS0108
#include "LibraryHardware.h"
#include "LibraryChar.h"
#include "LibraryUniversalDisplay.h"
#include "LibraryData.h"

void pic_init(void);

void main()
{
int i,j;
pic_init();                                                                             //initialize PIC
glcd_init();                                                                          //initialize GLCD
for(;;){
                for(i=0;i<8;i++){
                                CHIP_LEFT();
                                glcd_goto(i,0,0);
                                for(j=0;j<=63;j++) glcd_write(img1[128*i+j]);
                                CHIP_RIGHT();
                                glcd_goto(i,0,0);
                                for(j=0;j<=63;j++) glcd_write(img1[128*i+j+64]);
                }
                delay(1000);

                for(i=0;i<8;i++){
                                CHIP_LEFT();
                                glcd_goto(i,0,0);
                                for(j=0;j<=63;j++) glcd_write(img2[128*i+j]);
                                CHIP_RIGHT();
                                glcd_goto(i,0,0);
                                for(j=0;j<=63;j++) glcd_write(img2[128*i+j+64]);
                }
                delay(1000);
}             
}

void pic_init(void)
{
TRISA=0b00101111;
TRISB=0b00000000;
TRISC=0b00000000;
TRISD=0b00000000;
TRISE=0b00000111;
set_digital();
PORTA=0b00010000;
PORTB=0b00000000;
PORTC=0b00000000;
PORTD=0b00000000;
PORTE=0b00000000;
}

Tuesday, July 24, 2012

Touch Switch

This circuit demonstrates the principle and operation of application based on touch sensor. The circuit is divided into three parts: Input, 555 timer and output. A touch plate is used for the input and output can be seen across an LED or a buzzer. Some application of the circuit include touch based blinking lights, touch buzzer, touch switch etc.


The touch plates is connected to the trigger pin of the 555 timer IC. When we touch the touch plates the output of the touch plates becomes zero thereby providing an active low trigger to the IC 555. The IC is configured in the monostable mode .The output of the IC is a pulse whose frequency is set by theresistor (R1) and  capacitor (C1) according to the formula [F=1/(1.1*R*C)]. In this case it produces a pulse with frequency of about 0.9 hertz and time period of 1.1 seconds. In monostable mode pin7 (discharge pin) and pin6 (threshold pin) are shorted while R1 is connected between pin7 and Vcc and C1 is connected between pin 6 and ground. Reset pin (pin4) is connected to Vcc while control pin is connected to ground through a capacitor. The output can be observed on the LED, which glows for a small duration. This circuit can be used in the following applications:
To detect stray voltages produced by mains or to detect electrostatics build up in a room.
To make touch buzzers.
To implement touch switches like for a bell.
circuit 2, shows an improved version of this circuit. This circuit has a higher sensitivity as compared to circuit in figure 1. The output of the touch plate is connected to the base of npn transistor T1 (BC 547). The collector is connected to the Vcc through a resistor R1. The trigger pin of the IC is connected to the collector of the transistor. When no input is there on the base of the T1, T1 is in cut off state and hence the trigger pin is at logic high and therefore 555 do not produce any output. When we touch the plates T1 behaves like a closed switch trigger pin gets connected to ground, thereby producing the output at pin 3 of the IC.

Automatic Night Lamp


Ever imagined how the street lights would turn on automatically in the evening and go off in the morning? Is there anyone who comes early morning to turn off these lights? The following circuit can perform this job properly. This circuit uses the output from a simple light/dark activated circuit and drives a relay in its output which can be further coupled to switch on/off an electrical appliance in a household.
An appliance can be made dark or light activated by slightly changing the circuit’s configuration.  This idea finds numerous applications such as, automatic watering of gardens at evening, automatic night lamp, dark activated siren and so on.

 A light dependent resistor (LDR) is used in this circuit to provide input to a comparator of LM339 (refer Automatic lightdark indicator). The output pin of the comparator goes high depending on the configuration of LDR so that it can be made light or dark activated. This output is connected to a transistor T1 (BC 547) which acts as a switch for the relay.
The high output of the comparator provides the necessary forward bias to the base-emitter junction of the transistor T1. Thus T1 jumps from cut off to saturation state and collector current flows. This collector current energizes the relay coil. The magnetic field produced by the relay coil shifts its connection from NO state to NC. An appliance connected to NC contact gets switched on.
When the output of the comparator is low, it is insufficient to drive the transistor T1 to saturation. Hence T1 moves to cut off and the collector current ceases to flow. Thus the relay coil gets de-energized and it switches the state from NC to NO mode. It is important to note that resistor R2 (20k) is provided at the base of T1 to check the base current.

GAS LEAKAGE DETECTOR ALERT WITH MESSAGE TO MOBILE WITH GSM MODEM

Here is the ckt for gas leakage detection.gas sensor is directly connected to the microcontroller's ADC.
if gas is detected by the sensor ADC calculates how much amount of gas present in the air.If it is found a larger amount microcontroller switch ON an exhaust fan.At the same time a SMS send to the pre defined mobile number..

CODE
adc_lib.c
#include
#include
#define ADC_VREF_TYPE 0x00
// Read the AD conversion result
unsigned int read_adc(unsigned char adc_input)
{
ADMUX=adc_input|ADC_VREF_TYPE;
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
return ADCW;
}
void ADCinit()
{
ADMUX=ADC_VREF_TYPE;
ADCSRA=0x85;
}

uart_lib.c

#include
#include
#include
#define FOSC 4000000
void set_uartbaud(int BAUD)
{
        UBRRH = (unsigned char)((FOSC/16/BAUD-1)>>8);
        UBRRL = (unsigned char)(FOSC/16/BAUD-1);
        UCSRC|=(1<
        UCSRB|=(1<
}

void disable_uart()
{
        UCSRB&=~(1<
        UCSRB&=~(1<
}

void enable_uart_txcint()
{
        UCSRB|=(1<
}

void enable_uart_rxcint()
{
        UCSRB|=(1<
}

void enable_uart_udreint()
{
        UCSRB|=(1<
}

void disable_uart_txcint()
{
        UCSRB&=~(1<
}

void disable_uart_rxcint()
{
        UCSRB&=~(1<
}

void disable_uart_udreint()
{
        UCSRB&=~(1<
}

void sendchar_uart(char data)
{
        int temp;
        temp=UCSRA&(1<
        temp=temp>>UDRE;
        while(!temp)
        {

        }
        UDR=data;
}

char getchar_uart()
{
        // Wait until a byte has been received

        while((UCSRA&(1<

        // Return received data

        return UDR;

}

void sendstring_uart(char v[])
{
        int i;
        for(i=0;i
        {
                sendchar_uart(v[i]);
                _delay_ms(10);
        }
}



msg_display.c

#include "lcd_lib.h"

char A[200]=" ";
char B[20]=" ";
char E[10]="ATE0";
char T[20]="AT";
char c[20]="GAS LEAKAGE";
char h[20]="TEMP INCREASES";
char d[20]="+919999999999";//enter required number here
char e[20]="AT+CMGS=";
char f[20]="AT+CMGR=1";
char g[20]="AT+CMGD=1";
int i=0,j=0,k=0,l=0;
int status=0;
main(void)
{
        DDRB=255;
        LCDinit();
    LCDclr();
    ADCinit();
        set_uartbaud(9600);
        enable_uart_rxcint();
        sei();
        sendstring_uart(g);
                          _delay_ms(100);
                          sendchar_uart(0x0D);
                          _delay_ms(1000);
         sendstring_uart(E);
         _delay_ms(100);
         sendchar_uart(0x0D);
         _delay_ms(1000);
         sendstring_uart(T);
         _delay_ms(100);
         sendchar_uart(0x0D);
         _delay_ms(1000);
        while(1)
        {
                LCDcursorOFF();
                j=read_adc(0);
                LCDGotoXY(0,1);
                sprintf(B,"%2d     ",j);
                LCDdisplay(B);
                _delay_ms(100);
                 /*sendstring_uart(f);
                                  _delay_ms(100);
                                  sendchar_uart(0x0D);
                                  _delay_ms(1000);
        LCDGotoXY(0,0);
    LCDdisplay(A);
    LCDshiftRight(1);*/

   if(j>600)
    {
                        PORTB=0b00000011;_delay_ms(1000);
                        _delay_ms(1000);
                        _delay_ms(1000);
                        _delay_ms(1000);
                        //PORTB=2;_delay_ms(1500);
                        sendstring_uart(e);
                    _delay_ms(10);
                    sendchar_uart('"');
                    _delay_ms(10);
                    sendstring_uart(d);
                    _delay_ms(10);
                    sendchar_uart('"');
                    _delay_ms(10);
                    sendchar_uart(13);
                    _delay_ms(100);
                    sendstring_uart(c);
                    _delay_ms(10);
                    sendchar_uart(0X1A);
                    _delay_ms(10);
    }
    else
    {
            PORTB=0;
    }
        }
}
ISR(USART_RXC_vect)
{
        status=1;
        char c;
        c=UDR;
        if(c!=0x0D)
        {
                if(c!=0x0A)
                {
                        A[i]=c;
                        i++;
                }
        }
        if(i==300)
                i=0;
}


Sunday, July 22, 2012

Keyboard Shorcuts (Microsoft Windows)


More than 100 Keyboard Shortcuts
(for more Interesting posts Like Knowledge Is Power)
Keyboard Shorcuts (Microsoft Windows)
1. CTRL+C (Copy)
2. CTRL+X (Cut)


3. CTRL+V (Paste)
4. CTRL+Z (Undo)
5. DELETE (Delete)
6. SHIFT+DELETE (Delete the selected item permanently without placing the item in the Recycle Bin)
7. CTRL while dragging an item (Copy the selected item)
8. CTRL+SHIFT while dragging an item (Create a shortcut to the selected item)
9. F2 key (Rename the selected item)
10. CTRL+RIGHT ARROW (Move the insertion point to the beginning of the next word)
11. CTRL+LEFT ARROW (Move the insertion point to the beginning of the previous word)
12. CTRL+DOWN ARROW (Move the insertion point to the beginning of the next paragraph)
13. CTRL+UP ARROW (Move the insertion point to the beginning of the previous paragraph)
14. CTRL+SHIFT with any of the arrow keys (Highlight a block of text)
SHIFT with any of the arrow keys (Select more than one item in a window or on the desktop, or select text in a document)
15. CTRL+A (Select all)
16. F3 key (Search for a file or a folder)
17. ALT+ENTER (View the properties for the selected item)
18. ALT+F4 (Close the active item, or quit the active program)
19. ALT+ENTER (Display the properties of the selected object)
20. ALT+SPACEBAR (Open the shortcut menu for the active window)
21. CTRL+F4 (Close the active document in programs that enable you to have multiple documents open simultaneously)
22. ALT+TAB (Switch between the open items)
23. ALT+ESC (Cycle through items in the order that they had been opened)
24. F6 key (Cycle through the screen elements in a window or on the desktop)
25. F4 key (Display the Address bar list in My Computer or Windows Explorer)
26. SHIFT+F10 (Display the shortcut menu for the selected item)
27. ALT+SPACEBAR (Display the System menu for the active window)
28. CTRL+ESC (Display the Start menu)
29. ALT+Underlined letter in a menu name (Display the corresponding menu) Underlined letter in a command name on an open menu (Perform the corresponding command)
30. F10 key (Activate the menu bar in the active program)
31. RIGHT ARROW (Open the next menu to the right, or open a submenu)
32. LEFT ARROW (Open the next menu to the left, or close a submenu)
33. F5 key (Update the active window)
34. BACKSPACE (View the folder onelevel up in My Computer or Windows Explorer)
35. ESC (Cancel the current task)
36. SHIFT when you insert a CD-ROMinto the CD-ROM drive (Prevent the CD-ROM from automatically playing)
Dialog Box - Keyboard Shortcuts
1. CTRL+TAB (Move forward through the tabs)
2. CTRL+SHIFT+TAB (Move backward through the tabs)
3. TAB (Move forward through the options)
4. SHIFT+TAB (Move backward through the options)
5. ALT+Underlined letter (Perform the corresponding command or select the corresponding option)
6. ENTER (Perform the command for the active option or button)
7. SPACEBAR (Select or clear the check box if the active option is a check box)
8. Arrow keys (Select a button if the active option is a group of option buttons)
9. F1 key (Display Help)
10. F4 key (Display the items in the active list)
11. BACKSPACE (Open a folder one level up if a folder is selected in the Save As or Open dialog box)

Microsoft Natural Keyboard Shortcuts
1. Windows Logo (Display or hide the Start menu)
2. Windows Logo+BREAK (Display the System Properties dialog box)
3. Windows Logo+D (Display the desktop)
4. Windows Logo+M (Minimize all of the windows)
5. Windows Logo+SHIFT+M (Restorethe minimized windows)
6. Windows Logo+E (Open My Computer)
7. Windows Logo+F (Search for a file or a folder)
8. CTRL+Windows Logo+F (Search for computers)
9. Windows Logo+F1 (Display Windows Help)
10. Windows Logo+ L (Lock the keyboard)
11. Windows Logo+R (Open the Run dialog box)
12. Windows Logo+U (Open Utility Manager)
13. Accessibility Keyboard Shortcuts
14. Right SHIFT for eight seconds (Switch FilterKeys either on or off)
15. Left ALT+left SHIFT+PRINT SCREEN (Switc High Contrast either on or off)
16. Left ALT+left SHIFT+NUM LOCK (Switch the MouseKeys either on or off)
17. SHIFT five times (Switch the StickyKeys either on or off)
18. NUM LOCK for five seconds (Switch the ToggleKeys either on or off)
19. Windows Logo +U (Open Utility Manager)
20. Windows Explorer Keyboard Shortcuts
21. END (Display the bottom of the active window)
22. HOME (Display the top of the active window)
23. NUM LOCK+Asterisk sign (*) (Display all of the subfolders that are under the selected folder)
24. NUM LOCK+Plus sign (+) (Display the contents of the selected folder)
25. NUM LOCK+Minus sign (-) (Collapse the selected folder)
26. LEFT ARROW (Collapse the current selection if it is expanded, or select the parent folder)
27. RIGHT ARROW (Display the current selection if it is collapsed, or select the first subfolder)
Shortcut Keys for Character Map
After you double-click a character on the grid of characters, you can move through the grid by using the keyboard shortcuts:
1. RIGHT ARROW (Move to the rightor to the beginning of the next line)
2. LEFT ARROW (Move to the left orto the end of the previous line)
3. UP ARROW (Move up one row)
4. DOWN ARROW (Move down one row)
5. PAGE UP (Move up one screen at a time)
6. PAGE DOWN (Move down one screen at a time)
7. HOME (Move to the beginning of the line)
8. END (Move to the end of the line)
9. CTRL+HOME (Move to the first character)
10. CTRL+END (Move to the last character)
11. SPACEBAR (Switch between Enlarged and Normal mode when a character is selected)
Microsoft Management Console (MMC)
Main Window Keyboard Shortcuts
1. CTRL+O (Open a saved console)
2. CTRL+N (Open a new console)
3. CTRL+S (Save the open console)
4. CTRL+M (Add or remove a console item)
5. CTRL+W (Open a new window)
6. F5 key (Update the content of all console windows)
7. ALT+SPACEBAR (Display the MMC window menu)
8. ALT+F4 (Close the console)
9. ALT+A (Display the Action menu)
10. ALT+V (Display the View menu)
11. ALT+F (Display the File menu)
12. ALT+O (Display the Favorites menu)

MMC Console Window Keyboard Shortcuts
1. CTRL+P (Print the current page or active pane)
2. ALT+Minus sign (-) (Display the window menu for the active console window)
3. SHIFT+F10 (Display the Action shortcut menu for the selected item)
4. F1 key (Open the Help topic, if any, for the selected item)
5. F5 key (Update the content of all console windows)
6. CTRL+F10 (Maximize the active console window)
7. CTRL+F5 (Restore the active console window)
8. ALT+ENTER (Display the Properties dialog box, if any, for theselected item)
9. F2 key (Rename the selected item)
10. CTRL+F4 (Close the active console window. When a console has only one console window, this shortcut closes the console)
Remote Desktop Connection Navigation
1. CTRL+ALT+END (Open the Microsoft Windows NT Security dialog box)
2. ALT+PAGE UP (Switch between programs from left to right)
3. ALT+PAGE DOWN (Switch between programs from right to left)
4. ALT+INSERT (Cycle through the programs in most recently used order)
5. ALT+HOME (Display the Start menu)
6. CTRL+ALT+BREAK (Switch the client computer between a window and a full screen)
7. ALT+DELETE (Display the Windows menu)
8. CTRL+ALT+Minus sign (-) (Place a snapshot of the active window in the client on the Terminal server clipboard and provide the same functionality as pressing PRINT SCREEN on a local computer.)
9. CTRL+ALT+Plus sign (+) (Place asnapshot of the entire client window area on the Terminal server clipboardand provide the same functionality aspressing ALT+PRINT SCREEN on a local computer.)

Microsoft Internet Explorer Keyboard Shortcuts
1. CTRL+B (Open the Organize Favorites dialog box)
2. CTRL+E (Open the Search bar)
3. CTRL+F (Start the Find utility)
4. CTRL+H (Open the History bar)
5. CTRL+I (Open the Favorites bar)
6. CTRL+L (Open the Open dialog box)
7. CTRL+N (Start another instance of the browser with the same Web address)
8. CTRL+O (Open the Open dialog box,the same as CTRL+L)
9. CTRL+P (Open the Print dialog box)
10. CTRL+R (Update the current Web page)
11. CTRL+W (Close the current window)

Friday, July 20, 2012

Office 2013


OFFICE 2013 New Features–A new Office
Office 2013 preview got released recently and got time to install and test it out. Some features are really amazing and nice implementation. Here are my views on it.
New Office is Cloud friendly and ready to use on the touchscreen. This is really an amazing feature to Office. Another top new feature in office 2013 suite is the cursor. When you are typing the text, the cursor just move forward just like a line. It don’t appear like blinking anymore. I am liking this much and like to type more and more…
The new interface is looking clean but not with much colors though. A plain and clean white color ribbon. The ribbon and icons are a bit big when compared to office 2010 icons. This will be good for touchscreen users.



Top Features:Word
  • Import, edit and save PDF
    : We can import an existing PDF file directly to Microsoft WORD 2013 and then do edits and then save back to either word or PDF format. This is the number one feature which I liked much in Office 2013 suite.
  • Ability to connect to online services
    : You can directly search web using Bing for keyword search, images or Videos without leaving word. And then you can use/embed the HTML code in the word directly. You can also play the video directly in the word.
  • You can embed the online services like Flickr, SkyDrive etc. with document without leaving word.
  • Expand and Collapse
    : Now you can use the expand, collapse option in the word text. This is called "read" mode. You can expand, collapse a paragraph once you read it.
  • Resume Reading
    : Office 2013 will automatically bookmark the user last position in the document. After you reopened the document it can pick you where you left off.
Excel:
  • Flash Fill
    : If you have two columns and based on the first column, if you type the data in second column first row, then the Flash Fill predicts and fills the data accordingly for remaining rows in second column.
  • Quick analysis
    : If you select a range of values in Excel then the quick analysis tool will automatically conditional formats which helps us to understand the data easily.
  • Many chart options
    : There are many chart options and features available in Excel 2013.
Outlook:
  • Weather
    : New outlook has the best option to show the weather reports for next 3 days in the calendar. This helps us to change the plans in meetings and plan according to weather reports. Smile

  • Reply, Forward in POP-IN window
    : You can reply, forward emails in the pop-in window. When you are moving out of inbox, send items etc. and come back to same email the pop-in window still there and you can continue in typing text.



OneNote:
  • Onenote is now more powerful and looks very good. It is described as digital notebook from Microsoft.
  • Integration to Outlook
    : You can save the emails to Onenote directly from Outlook.
PowerPoint:
I didn’t spend much time in PowerPoint. I like to see how they improved the functionality in presenting something on projector… And there it wins me.

  • When we are presenting the PowerPoint presentation the presenter can see on his screen what is the next slide to present. This will give much information and help to the presenter what to give in next slide.
  • Clock on the screen
    : The presenter can keep tracking of the time how long she/he has been speaking. Smile
Many more features are there. I will document and post them as soon as I can. The bottom line I like Office 2013 much and it is going to be a huge success in Office suite so far which makes Microsoft to sit at top position.

Saturday, July 7, 2012

BCD Arithmatics


Introduction

Binary coded decimal arithmetic has fallen out of favor among modern hardware designers, and it is poorly supported in most modern programming languages, yet it is still occasionally appropriate. For example, when a numeric field of a record in a text file must be incremented, the methods presented here will be significantly faster than converting the textual value to a binary integer, incrementing, and then converting back to text.
For programmers with a devious sense of humor, these methods can be a very effective way to obfuscate code in languages such as C. These techniques are also historically significant. The DEC (now Compaq) Alpha architecture and the more recent Intel MMX extensions to the 80x86 architecture both supporting manipulation of vectors of small objects such as pixels packed into 64-bit words; the motive for this can be found in the much older ideas described here.
In the following sections, all arithmetic is assumed to be done in 32 bit registers (the algorithms are easily adapted to other word lengths), and neither carry out nor overflow are deemed significant. The code written for clarity, using C notation for operators and constants, with named temporary variables whenever a subexpression in the computation is cited in the text. Practical implementations will very likely use far fewer temporary variables.
All of the number representations discussed here are unsigned, although the subtraction operation rests on the use of ten's complement arithmetic, and this, in turn, suggests the use of the ten's complement operation for negation. In that case, number with a most significant digit greater than 5 can be interpreted as negative numbers.
For unsigned decimal numbers (or for 10's complement numbers with the same sign), the conventional unsigned binary comparison operators all remain applicable with these decimal represenations. Thus, if A and B are unsigned decimal numbers, and if > is the conventional unsigned greater-than operator for binary numbers, A>B will yield the correct results for comparing these numbers.

BCD Represenations
Binary coded decimal numbers may be represented in a number of ways. The most obvious is packed BCD, where each decimal digit is represented by a 4 bit field, and the digits are packed consecutively into a computer word. This scheme allows 4 digits to be packed into a 16 bit word, or 8 digits into a 32 bit word, as shown below.
    B31                             B15                            B0
    |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|
    |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|
    |   D7  |   D6  |   D5  |   D4  |   D3  |   D2  |   D1  |   D0  |
In addition to its efficiency, this format is useful because it is compatable with the use of hexidecimal I/O routines. Traditionally, packed BCD was viewed as requiring the use of special hardware to do BCD arithmetic, but in fact, it is possible to add two packed BCD numbers using a short sequence of conventional binary and logical operators.
Many early computers used 6-bit BCD codes, where each BCD digit was padded to 6 bits. This was compatable with the 36, 48 and 60 bit words used by many computers in the 1950's and 1960's, and on both the 36-bit IBM 704-709 series of machines (up through the 7044 and 7094) and 60-bit CDC 6600 series, this format was used to do BCD arithmetic without any special hardware support. On a modern 16 or 32 bit machine, this allows 3 or a bit more than 5 decimal digits per word, respectively.
    B31                             B15                            B0
    |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|
    |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|
    | D5|0 0|   D4  |0 0|   D3  |0 0|   D2  |0 0|   D1  |0 0|   D0  |
In the 32 bit format, productive use can be made of the fractional digit D5 for carry detection and propagation in extended precision arithmetic operations.
It should be noted that in most historically important 6-bit BCD collating sequences, all numerals other than zero were represented as shown above, while zero was sometimes represented by the binary code 1010, allowing the 6-bit code 000000 to be used for space. Ones in the two most significant bits of each 6-bit byte were used in the codes for letters and punctuation marks. See material on punched card codes for more detail on this subject.
The methods discussed here can be extended to other padding systems in obvious ways. For example, 6 5-bit fields can be packed into a 32-bit word, with one bit of padding between BCD digits. Alternately, 3 bits of padding can be added between digits, so that a 32-bit word holds 4 complete 7-bit fields, plus 4 bits that can be used for a 5th BCD digit.
Padding each BCD digit to fill an 8 bit byte is quite practical, but this inefficient representation is not particularly interesting except in the special case where each digit is directly represented by its ASCII code, as follows:
    B31                             B15                            B0
    |_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|
    |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|
    |0 0 1 1|   D3  |0 0 1 1|   D2  |0 0 1 1|   D1  |0 0 1 1|   D0  |
Of course, the same approach can be used for EBCDIC, using 0xF for a pad digit instead of 0x3. It is quite practical to do arithmetic operations directly on all of these representations!
Packed BCD Arithmetic
Validity Checking
The least significant 7 digits of a packed BCD number may be tested for validity as follows:
    valid(a)
       t1 = a + 0x06666666
       t2 = a ^ 0x06666666
       t3 = t1 ^ t2
       t4 = t3 & 0x11111110
       if t4 nonzero, a is invalid
This code deliberately ignores D7, the most significant digit, because the arithmetic operators presented here allow this digit to hold values up to 15. To understand this code, note that binary addition of 6 to each digit, to produce t1, will cause any digit with a value greater than 9 to generate a carry into the next higher digit.
t2 is similar to t1, in the sense that exclusive-oring is similar to adding. The two will be equal in bits where there was no carry in to that position, but they will differ in bits where there was a carry in. Therefore, t3 holds a one wherever there was a carry into a bit of t1, and t4 holds a 1 wherever there was a carry into a BCD digit of t1. Since the addition used to produce t1 should not produce such carries for a valid BCD number, t4 should be zero!
    valid(a)
       t1 = a + 0x06666666
       t2 = t1 ^ a
       t3 = t2 & 0x11111110
       if t3 nonzero, a is invalid
The above improvement was suggested by John Mertus at Brown University; Here, note that adding 6 to a 4-bit nibble of a produces a carry out of that nibble if the nibble is invalid, but also, adding 6 does not change the least significant bit. By exclusive oring the result in t1 with a to make t2, the least significant bit of each nibble is compared with the original. Finally, we ignore all the other bits and demand that all the least significant bits be zero, indicating no carry from the previous bit positions.
Antoine Schweitzer-Chaput suggested an alternative validity check to me. Note that all BCD digits of the form 0xxx are valid, as are digits of the form x00x. Therefore, if d is a BCD digit, we can test it for validity with:
   valid(d)
     if (d & 0x8) is zero or (d & 0x6) is zero
Extending this to packed BCD is a fun challenge.
Addition
The code to add two BCD numbers must solve the problem of propagating carries from one BCD digit to the next, and the logic for doing so rests on many of the mechanisms introduced above.
    add(a,b)
       t1 = a + 0x06666666
       t2 = t1 + b
       t3 = t1 ^ b
       t4 = t2 ^ t3
       t5 = ~t4 & 0x11111110
       t6 = (t5 >> 2) | (t5 >> 3)
       return t2 - t6
Here, the addition used to form t1 should not produce any carries, since we assume that t1 is valid. The addition used to form t2 will produce a carry exactly when the decimal addition of two digits in the operands would produce a carry, and these are the carries we are concerned with.
In t2, the digits in each position that produced a carry will have the correct value, but the digits in positions that did not produce a carry will contain an excess 6. The problem, then, is to remove the extra 6 from each digit that did not generate a carry.
Note that t2 and t3 differ wherever there was a carry, so t4 records all carries into positions in the sum. Therefore, t5 holds the inverse of each of the 7 carries between successive decimal digits of the sum. This bit pattern is used to generate t6, where each digit is either 6 where the corresponding digits of the sum did not generate a carry or 0 where they did. Subtracting this from t2 produces the correct BCD sum.
Note that the most significant digit of the sum will exceed 9 if there should have been a carry out of that position. Furthermore, there is no easy way to detect this carry! Out of range values in the high digit may be of some limited use, but in general, the top BCD digit should only be used to accumulate carrys out of 7-digit BCD operands. If its use is limited in this way, the numbers will always be positive and will never produce a 2's complement overflow.
Subtraction
To subtract two numbers, 10's complement addition should be used. To compute the 10's complement of a number, subtract it digit-by-digit from 99999999 (decimal) and then add 1, as follows:
    tencomp(a)
       t1 = 0xF9999999 - a
       return add( t1, 0x00000001 )
Here, t1 is (mostly) the 9's complement of the argument, except that the topmost digit is the 15's complement because of the redundancy allowed in that digit position. There is room for optimization in this code! As a first step, the code for addition has been substituted into place (with appropriate variable renaming).
    tencomp(a)
       t1 = 0xF9999999 - a
       t2 = t1 + 0x06666666
       t3 = t2 + 0x00000001
       t4 = t2 ^ 0x00000001
       t5 = t3 ^ t4
       t6 = ~t5 & 0x11111110
       t7 = (t6 >> 2) | (t6 >> 3)
       return t3 - t7
This reduces to the following obscure bit of code, with variables renamed again:
    tencomp(a)
       t1 = 0xFFFFFFFF - a
       t2 = - a
       t3 = t1 ^ 0x00000001
       t4 = t2 ^ t3
       t5 = ~t4 & 0x11111110
       t6 = (t5 >> 2) | (t5 >> 3)
       return t2 - t6
6-bit BCD Arithmetic
Validity Checking
All 5 full digits of a 6-bit BCD number may be tested for validity as follows:
    valid(a)
       t1 = a + 006666666666
       t2 = t1 & 006060606060
       if t2 = 006060606060, a is valid
To understand this code, note that binary addition of 066 to each digit, to produce t1, will cause any digit with a value greater than 9 to generate a carry into the next higher digit. The lower 6 forces a carry out of any digit greater than 9, while the higher 6 sets the pad bits and allows the carry to propagate up to the next higher digit position.
t2 holds just the pad bits in the result from t1. Where no carry was propagated in the computation of t1, these will be set, while where a carry was propagated through the padding, they will be reset. A valid 6-bit BCD number should not have generated any carry, so all of the pad bits should be set!
Addition
The code to add two 5-digit 6-bit BCD numbers must solve the problem of propagating carries from one BCD digit to the next, and the logic for doing so rests on the mechanisms just introduced:
    add(a,b)
       t1 = a + b + 006666666666
       t2 = t1 & 006060606060
       return t1 - (t2 >> 3)
Here, the addition used to form t1 adds an extra 6 to each BCD digit, forcing a carry out of that digit if the sum exceeds 9, and the same constant also includes ones in each pad bit in order to force this cary to propagate up to the next higher digit.
In t1, the digits in each position that produced a carry will have the correct value, but the digits in positions that did not produce a carry will contain an excess 6. The problem, is to remove this 6 from each digit that did not generate a carry.
t2 contains just the pad bits from the sum. For those digits that did not produce a carry, the pad bits will still be set to one. For those digits that produced a carry, the pad bits will be set to zero by the propagagion of the carry.
Shifting t2 3 places right produces a 6 in each digit position that did not generate a carry and zero elsewhere. Subtracting this from t1 produces the required correction!
A carry out from the 5-digit BCD sum will appear in partial digit, D5, that occupies the topmost 2 bits of the 32 bit number.
Subtraction
To subtract two numbers, 10's complement addition should be used. To compute the 10's complement of 5-digit 6-bit BCD number, subtract it digit-by-digit from 99999 (decimal) and then add 1, as follows:
    tencomp(a)
       t1 = 001111111111 - a
       return add( t1, 000000000001 )
Here, t1 is the 9's complement of the argument (note that 11 octal is 9 decimal). There is considerable room for optimization in this! Substituting the definition of add and renaming the variables to avoid collision, we get:
    tencomp(a)
       t1 = 001111111111 - a
       t2 = t1 + 000000000001 + 006666666666
       t3 = t2 & 006060606060
       return t2 - (t3 >> 3)
Rearranging terms and renaming temporaries gives:
    tencomp(a)
       t1 = (001111111111 - a)
           + 000000000001
           + 006666666666
       t2 = t1 & 006060606060
       return t1 - (t2 >> 3)
Which simplifies to:
    tencomp(a)
       t1 = 010000000000 - a
       t2 = t1 & 006060606060
       return t1 - (t2 >> 3)
ASCII Arithmetic
Validity Checking
To verify that a 4-digit ASCII string contains only valid BCD codes, techniques similar to those used for packed BCD and 6-bit BCD can be used:
    valid(a)
       t1 = a + 0xC6C6C6C6
       t2 = t1 & 0xF0F0F0F0
       if t2 = 0xF0F0F0F0, a is valid
To understand this code, note that binary addition of 0xC6 to each digit, to produce t1, will cause any digit with a value greater than 9 to generate a carry into the next higher digit. The lower 6 forces a carry out of any digit greater than 9, while the higher 0xC sets those pad bits which were not already set in the ASCII representation of the digit, thus allowing the carry to propagate up to the next higher digit position.
t2 holds just the pad bits from t1. Where no carry was propagated in the computation of t1, these will be set, while where a carry was propagated, they will be reset. A valid 6-bit BCD number should not have generated any carry, so all pad bits should be set!
Validity checking is more complex if blank and zero are to be interchangable, and more complex still if only leading blanks are allowed. On the other hand, oring 0x10101010 with a potential number converts all blanks to zeros, while also converting certain punctuation marks to other numerals. In certain applications, this may be a reasonable way to deal with blanks.
Addition
The code to add two 4-digit ASCII numbers must solve the problem of propagating carries from one BCD digit to the next, and the logic for doing so rests on the mechanisms just introduced:
    add(a,b)
       t1 = a + b + 0x96969696
       t2 = t1 & 0x30303030
       t3 = t1 - (t2 >> 3)
       return (t3 & 0x0F0F0F0F) | 0x30303030
Here, the addition used to form t1 adds an extra 6 to each BCD digit, forcing a carry out of that digit if the sum exceeds 9. In addition, it sets those pad bits which would not already be set by the padding included in ASCII for each character. This forces carry propagation up to the next higher digit.
In t1, the digits in each position that produced a carry will have the correct value, but the digits in positions that did not produce a carry will contain an excess 6.
t2 contains the two least significant bits of the padding from the sum; these bits will be 1 where no carry was propagated, so they can be shifted to subtract the excess 6 from the adjacent digit of the sum. This corrected sum, in t3 still contains the incorrect values in the pad fields. No matter what we do, it seems to take two extra binary operations to restore the pad fields to their proper values.
The carry out from the 4-digit ASCII sum can be extracted from the pad bits of any of the temporary variables used above, so no digits are wasted in extended precision ASCII arithmetic.
By all means, if your purpose is to write obfuscated code, and if your programming language allows it, substitute ASCII literals for the hex constants wherever possible, as follows:
    add(a,b)
       t1 = a + b + 0x96969696
       t2 = t1 & '0000'
       t3 = t1 - (t2 >> 3)
       return (t3 & 0x0F0F0F0F) | '0000'
Subtraction
To subtract two numbers, 10's complement addition should be used. To compute the 10's complement of a number, subtract it digit-by-digit from 9999 (decimal) and then add 1, as follows:
    tencomp(a)
       t1 = 0x69696969 - a
       return add( t1, 0x30303031 )
Here, t1 is the 9's complement of the argument; the tricky aspect in this case is that the pad bits of the argument are nonzero, so the constant 9999 must be padded strangely to create the correct results. In any case, there is considerable room for optimization in this code! Substituting the code for addition and renaming temporaries gives:
    tencomp(a)
       t1 = 0x69696969 - a
       t2 = t1 + 0x30303031 + 0x96969696
       t3 = t2 & 0x30303030
       t4 = t2 - (t3 >> 3)
       return (t4 & 0x0F0F0F0F) | 0x30303030
Combining terms, renaming, and simplifing the result gives the following strange bit of code:
    tencomp(a)
       t1 = 0x20202020 - a
       t2 = t1 & 0x30303030
       t3 = t1 - (t2 >> 3)
       return (t3 & 0x0F0F0F0F) | 0x30303030
Of course, if your purpose is to write obfuscated code, by all means substitute ASCII literals for the hex constants wherever possible, creating:
    tencomp(a)
       t1 = '    ' - a
       t2 = t1 & '0000'
       t3 = t1 - (t2 >> 3)
       return (t3 & 0x0F0F0F0F) | '0000'
Much of the complexity of the above code is imposed by computations that determine the carry out of each digit of the BCD sum. Hardware that allows the carry propagation from bit to bit of the adder to be interrupted at selected points can greatly speed these computations. Both the DEC (later Compaq) Alpha and the Intel MMX extensions to the 80x86 family provide for this, allowing 64 bit words to be divided into many subfields, with carry propagation from field to field interrupted, and with the carries captured in a form allowing their manipulation. These facilities are not exposed to the high level language programmer, but they are used intensively in carefully handcrafted assembly-language routines for common vector operations such as those involved in pixel manipulation of graphics images.