CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Barcode Decoder Source Code

 
Post new topic   Reply to topic    CCS Forum Index -> Code Library
View previous topic :: View next topic  
Author Message
chingB



Joined: 29 Dec 2003
Posts: 81

View user's profile Send private message

Barcode Decoder Source Code
PostPosted: Sat Jul 09, 2005 12:56 am     Reply with quote

Hi,

I am sharing my barcode decoder source code. I guess this would be helpful in the community.

I use a Barcode OEM Slot Type Module from FameTech or Tysso at http://www.barcode-manufacturer.com/ or at http://www.fametech.com.tw/. The exact part number is SR-070 and I use the infra-red models. You can also use 1022WM from Cipher Lab at http://www.cipherlab.com/en/.

The decoder source code:
Code:

#define ZERO_VAL                    0
#define ONE_VAL                     1
#define TWO_VAL                     2
#define THREE_VAL                   3
#define FOUR_VAL                    4
#define EIGHT_VAL                   8

#define ROW_INDEX                   4
#define COL_INDEX                   10
#define MODULO_43                   43  // barcode check digit calculation

#define REVERSE_SWIPE               110 // the badge id is swipe reverse
#define FORWARD_SWIPE               111 // the badge id is swipe forward


#define BARCODE_DATA_COUNT          8   // to char data per badge id
#define BARS_PER_CODE               5   // number of bars per char

// number of spaces per char
#define SPACES_PER_CODE             ((BARS_PER_CODE) - (ONE_VAL))

// half the barcode data count
#define HALF_BARCODE_DATA_COUNT     ((BARCODE_DATA_COUNT) / (TWO_VAL))

// maximum number of bars per badge id
#define MAX_BAR_COUNT               ((BARCODE_DATA_COUNT) * (BARS_PER_CODE))

// maximum number of spaces per badge id
#define MAX_SPACE_COUNT             ((MAX_BAR_COUNT) - (ONE_VAL))



//----------------//
// T3CON Register //
//----------------//
#define T3CON_BASE                  0xFB1
#define T3CON                       ((unsigned int *)T3CON_BASE)


boolean CaptureMode = FALSE;        // FALSE-Falling, TRUE-Rising capture
boolean BarStart = FALSE;           // TRUE-barcode capture started
boolean BarEnd = FALSE;             // TRUE-barcode capture ended
boolean SkipSpaceDone = FALSE;      // TRUE-skip first space barcode capture

int BarCnt = ZERO_VAL;              // bars counter
int SpaceCnt = ZERO_VAL;            // space counter
int16 BarTable[MAX_BAR_COUNT];      // bars 16-bit time capture value
int16 SpaceTable[MAX_BAR_COUNT];    // spaces 16-bit time capture value

byte BarcodeTable[BARCODE_DATA_COUNT];      // decoded barcode data
byte RawBarTable[BARCODE_DATA_COUNT];       // raw bar data table
byte RawSpaceTable[BARCODE_DATA_COUNT];     // raw space data table

byte BarPatternTable[COL_INDEX] = {
    17, 9, 24, 5, 20, 12, 3, 18, 10, 6
};

byte RevBarPatternTable[COL_INDEX] = {
    17, 18, 3, 20, 5, 6, 24, 9, 10, 12
};

byte Code3of9Table[ROW_INDEX][COL_INDEX] = {
    {'K','L','M','N','O','P','Q','R','S','T'},
    {'A','B','C','D','E','F','G','H','I','J'},
    {'1','2','3','4','5','6','7','8','9','0'},
    {'U','V','W','X','Y','Z','-','.',' ','*'}
};


// bars and space average time variables
typedef struct BarSpaceAveStruct
{
    int16 BarsAverageTime;
    int16 SpacesAverageTime;
} BAR_SPACE_AVE_STRUCT;


boolean ClockTick = FALSE;
int TickCnt = ZERO_VAL;



#int_timer0
void timer0_isr(void)
{
    TickCnt++;

    if (    TickCnt > THREE_VAL
         && ClockTick == FALSE)
    {
        ClockTick = TRUE;

        // output toggle PIN_A0 (LED Blinker)
        #asm
        BCF 0xF92.0
        BTG 0xF89.0
        #endasm
    }
    clear_interrupt(int_timer0);
}


#int_timer1
void timer1_isr()
{
    // timer overflow for no barcode data to capture
    disable_interrupts(int_timer1);
    if (BarStart == TRUE)
    {
        BarStart = FALSE;       // reset bar capture to initial state
        SkipSpaceDone = FALSE;  // reset skip space to capture first space
        CaptureMode = FALSE;    // reset to falling edge capture

        BarEnd = TRUE;          // barcode capture has ended
        BarCnt = ZERO_VAL;      // reset bars counter
        SpaceCnt = ZERO_VAL;    // reset spaces counter
    }
    clear_interrupt(int_timer1);
}


#int_ccp1
void ccp1_isr()
{
    if (    BarCnt >= MAX_BAR_COUNT
         && SpaceCnt > MAX_SPACE_COUNT)
    {
        // disable CCP1 if bars and spaces count exceeds maximum count
        disable_interrupts(int_ccp1);
    }

    if (CaptureMode == FALSE) // falling edge capture (bars)
    {
        CaptureMode = TRUE;
        if (BarStart == TRUE)
        {
            BarTable[BarCnt++] = CCP_1;
        }
        else
        {
            BarStart = TRUE;
            clear_interrupt(int_timer1);
            enable_interrupts(int_timer1);
        }
    }
    else // rising edge capture (spaces)
    {
        CaptureMode = FALSE;
        if (SkipSpaceDone == TRUE)
        {
            SpaceTable[SpaceCnt++] = CCP_1;
        }
        else
        {
            SkipSpaceDone = TRUE;
        }
    }

    // toggle capture CCP1CON mode select bit
    #asm
    MOVLW 0x01
    XORWF 0xFBD, F
    #endasm

    // reset timer1
    set_timer1(ZERO_VAL);
    clear_interrupt(int_ccp1);
}


void init_mcu(void)
{
   delay_ms(1000);          // delay for 1 seconds (stabilized MCU?)

   output_float(PIN_C2);    // set to input for CCP1 capture

   clear_interrupt(int_timer1);
   clear_interrupt(int_ccp1);

   setup_adc_ports(NO_ANALOGS);     // setup PortA to digital I/O
   setup_ccp1(CCP_CAPTURE_FE);      // set CCP1 to falling edge capture

   setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);    // 20M/(4*8*65536)
   set_timer1(ZERO_VAL);

   clear_interrupt(int_timer0);
   setup_timer_0(RTCC_INTERNAL | RTCC_DIV_16);  // 20M/(4*16*65536)
   set_timer0(ZERO_VAL);

   enable_interrupts(INT_CCP1);     // enable CCP1 interrupt on falling edge
   enable_interrupts(int_timer0);
   enable_interrupts(global);       // enable global interrupt

   output_low(PIN_A0);
   return;
}


void clear_barcode_buffers(void)
{
    int Idx;

    for (Idx = ZERO_VAL;
         Idx < MAX_BAR_COUNT;
         Idx++)
    {
        BarTable[Idx] = ZERO_VAL;
        SpaceTable[Idx] = ZERO_VAL;
    }

    for (Idx = ZERO_VAL;
         Idx < BARCODE_DATA_COUNT;
         Idx++)
    {
        BarcodeTable[Idx] = ZERO_VAL;
        RawBarTable[Idx] = ZERO_VAL;
        RawSpaceTable[Idx] = ZERO_VAL;
    }

    return;
}


void display_code(void)
{
    int Idx;

    printf("\n\rBarcode = ");
    for (Idx = ZERO_VAL;
         Idx < BARCODE_DATA_COUNT;
         Idx++)
    {
        printf("%c",BarcodeTable[Idx]);
    }
   
    return;
}


BAR_SPACE_AVE_STRUCT get_average_time(int BarIdx, int SpaceIdx)
{
    int Idx;
    BAR_SPACE_AVE_STRUCT Midean;

    *(unsigned int32 *)&Midean = ZERO_VAL;

    for(Idx = ZERO_VAL;
        Idx < BARS_PER_CODE;
        Idx++)
    {
        Midean.BarsAverageTime += BarTable[BarIdx + Idx];

        if (Idx < SPACES_PER_CODE)
        {
            Midean.SpacesAverageTime += SpaceTable[SpaceIdx + Idx];
        }
    }

    Midean.BarsAverageTime /= BARS_PER_CODE;

    Midean.SpacesAverageTime /= SPACES_PER_CODE;

    return Midean;
}


void get_raw_code(void)
{
    int  BarIdx, SpaceIdx;
    int  Idx, TableIdx;
    byte BarPattern, SpacePattern;
    BAR_SPACE_AVE_STRUCT Midean;

    BarIdx = ZERO_VAL;
    SpaceIdx = ZERO_VAL;

    for (TableIdx = ZERO_VAL;
         TableIdx < BARCODE_DATA_COUNT;
         TableIdx++)
    {
        BarPattern = ZERO_VAL;
        SpacePattern = ZERO_VAL;
        Midean = get_average_time(BarIdx, SpaceIdx);

        for (Idx = ZERO_VAL;
             Idx < BARS_PER_CODE;
             Idx++)
        {
            BarPattern <<= ONE_VAL;
            if (BarTable[BarIdx] > Midean.BarsAverageTime)
            {
                BarPattern |= ONE_VAL;
            }

            if (    SpaceIdx < MAX_SPACE_COUNT
                 && Idx < SPACES_PER_CODE)
            {
                SpacePattern <<= ONE_VAL;
                if (SpaceTable[SpaceIdx] > Midean.SpacesAverageTime)
                {
                    SpacePattern |= ONE_VAL;
                }
            }

            BarIdx++;
            SpaceIdx++;
        }

        RawBarTable[TableIdx] = BarPattern;
        RawSpaceTable[TableIdx] = SpacePattern;
    }

    return;
}


byte reverse_special_char_space(int Spaces)
{
    if (Spaces == 14)
        return 7;
    else if (Spaces == 13)
        return 11;
    else if (Spaces == 11)
        return 13;
    else if (Spaces == 7)
        return 14;
    else
        return Spaces;
}


byte get_code_3of9(byte BarPattern, byte SpacePattern, boolean Mode)
{
    byte Result='@';
    int ColIdx, RowIdx;

    if (BarPattern == ZERO_VAL)
    {
        if (Mode == FORWARD_SWIPE)
            SpacePattern = reverse_special_char_space(SpacePattern);

        if (SpacePattern == 14)
            return '$';
        else if (SpacePattern == 13)
            return '/';
        else if (SpacePattern == 11)
            return '+';
        else if (SpacePattern == 7)
            return '%';
        else
            return Result;
    }

    else
    {
        for (RowIdx = ZERO_VAL;
             RowIdx < ROW_INDEX;
             RowIdx++)
        {
            if (SpacePattern == (ONE_VAL << RowIdx))
            {
                for (ColIdx = ZERO_VAL;
                     ColIdx < COL_INDEX;
                     ColIdx++)
                {
                    if (    Mode == REVERSE_SWIPE
                         && BarPatternTable[ColIdx] == BarPattern)
                    {
                        return Code3of9Table[RowIdx][ColIdx];
                    }
                    else if (    Mode == FORWARD_SWIPE
                              && RevBarPatternTable[ColIdx] == BarPattern)
                    {
                        return Code3of9Table[THREE_VAL - RowIdx][ColIdx];
                    }
                    else
                        #asm nop #endasm
                }

                break;
            }
        }

        return Result;
    }
}


byte get_ref_code3of9(byte ch)
{
    if ( ch >= '0' && ch <= '9')
        return (ch - 48);
    else if (ch >= 'A' && ch <= 'Z')
        return (ch - 55);
    else if (ch == '-')
        return 36;
    else if (ch == '.')
        return 37;
    else if (ch == ' ')
        return 38;
    else if (ch == '$')
        return 39;
    else if (ch == '/')
        return 40;
    else if (ch == '+')
        return 41;
    else if (ch == '%')
        return 42;
   else return 100;
}


boolean get_check_digit(void)
{
    byte Idx, BarData;
    byte CheckDigit=0;

    for (Idx = ONE_VAL;
         Idx < BARCODE_DATA_COUNT - TWO_VAL;
         Idx++)
    {
        BarData = BarcodeTable[Idx];
        CheckDigit += get_ref_code3of9(BarData);
    }

    BarData = BarcodeTable[BARCODE_DATA_COUNT - TWO_VAL];

    if ((CheckDigit % MODULO_43) == get_ref_code3of9(BarData))
        return TRUE;

    return FALSE;
}


void reverse_barcode_table(byte *Table)
{
    byte Idx1, Idx2;
    byte ch;

    Idx2 = BARCODE_DATA_COUNT - ONE_VAL;
    for (Idx1 = ZERO_VAL;
         Idx1 < HALF_BARCODE_DATA_COUNT;
         Idx1++, Idx2--)
    {
        ch = Table[Idx1];
        Table[Idx1] = Table[Idx2];
        Table[Idx2] = ch;
    }
   
    return;
}


void interpret_code(void)
{
    int Idx;

    for (Idx = ZERO_VAL;
         Idx < BARCODE_DATA_COUNT;
         Idx++)
    {
        BarcodeTable[Idx] = get_code_3of9(RawBarTable[Idx],
                                          RawSpaceTable[Idx],
                                          REVERSE_SWIPE);
    }

    if (get_check_digit() == FALSE)
    {
        for (Idx = ZERO_VAL;
             Idx < BARCODE_DATA_COUNT;
             Idx++)
        {
            BarcodeTable[Idx] = get_code_3of9(RawBarTable[Idx],
                                              RawSpaceTable[Idx],
                                              FORWARD_SWIPE);
        }

        reverse_barcode_table(BarcodeTable);
        if (get_check_digit() == FALSE)
        {
            // error reading badge id
            printf("\n\rBarcode Read Error!");
            clear_barcode_buffers();
        }
        else
            display_code();         // display badge id
    }
    else
        display_code();             // display badge id
   
    clear_interrupt(int_ccp1);      // clear CCP1 interrupt flag
    enable_interrupts(int_ccp1);    // re-enable CCP1 interrupt
   
    return;
}



The main loop:
Code:

void main(void)
{
    int T3ConVal;

    init_mcu();                 // initialize mcu
    clear_barcode_buffers();    // clear all buffers

    T3ConVal = *T3CON;          // read T3CON register
    T3ConVal &= 0x9F;           // timer1 is clock source for CCP1 module
    *T3CON = T3ConVal;          // update T3CON register

    while (TRUE)
    {
       if (ClockTick == TRUE)
       {
          TickCnt = 0;
          ClockTick = 0;
       }

       if (BarEnd == TRUE)
       {
          BarEnd = FALSE;
          get_raw_code();       // get raw code of captured data
          interpret_code();     // interpret captured data
       }
    }
}



The Serial Output:
Code:

\0A                                                                         
Barcode = *RB1231*\0A                                                       
Barcode Read Error!\0A0D                                                     
Barcode Read Error!\0A\0D                                                   
Barcode Read Error!\0A\0D                                                   
Barcode Read Error!\0A\0D                                                   
Barcode Read Error!\0A\0D                                                   
Barcode Read Error!\0A\0D                                                   
Barcode Read Error!\0A\0D                                                   
Barcode = *RB1231*\0A \0D                                                   
Barcode = *RB1231*\0A\0D                                                     
Barcode = *RB1231*\0A\0D                                                     
Barcode = *RB1231*\0A\0D                                                     
Barcode = *MB2710*\0A\0D                                                     
Barcode Read Error!\0A0D                                                     
Barcode = *MB2710*\0A \0D                                                   
Barcode Read Error!\0A0D                                                     
Barcode = *MB2710*\0A \0D                                                   
Barcode Read Error!\0A0D                                                     
Barcode = *MB2710*\0A \0D                                                   
Barcode = *RB1231*   \0D


Hope this would help.
Thank you.
-
grinch



Joined: 06 Feb 2006
Posts: 2

View user's profile Send private message

barcode reader to pic16f877a
PostPosted: Mon Feb 06, 2006 5:32 am     Reply with quote

hi chingB!

i have project...theres a barcode reader(ps/2) and its connected to a pic16f877 any idea about that...?
grinch



Joined: 06 Feb 2006
Posts: 2

View user's profile Send private message

barcode reader to pic16f877a
PostPosted: Mon Feb 06, 2006 6:02 am     Reply with quote

hi!

do you a schematic diagram of what kind of ic's u r are using?

can i see it..
FGiordani



Joined: 25 Dec 2005
Posts: 4

View user's profile Send private message MSN Messenger

Re: Barcode Decoder Source Code
PostPosted: Thu Feb 16, 2006 10:12 am     Reply with quote

Hi,

I'm Brazilian.I need of your hardware schematic of barcode circuit.
This code work for PIC16F877? Which Microchip use?

Thanks
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Feb 16, 2006 12:36 pm     Reply with quote

ChingB has not posted on the forum for 6 months. He has probably
left the forum.
chingB



Joined: 29 Dec 2003
Posts: 81

View user's profile Send private message

PostPosted: Fri Mar 31, 2006 12:23 am     Reply with quote

PCM programmer wrote:
ChingB has not posted on the forum for 6 months. He has probably
left the forum.


Sorry Guys I've been busy lately with my company projects.

I am now working with BitMicro (http://www.bitmicro.com) as a firmware engineer.

As of the moment I don't have a spare time but I will try my best to be part of the community esp. I luv doing firmware programming using PIC.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> Code Library All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group