|
|
View previous topic :: View next topic |
Author |
Message |
chingB
Joined: 29 Dec 2003 Posts: 81
|
Barcode Decoder Source Code |
Posted: Sat Jul 09, 2005 12:56 am |
|
|
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
|
barcode reader to pic16f877a |
Posted: Mon Feb 06, 2006 5:32 am |
|
|
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
|
barcode reader to pic16f877a |
Posted: Mon Feb 06, 2006 6:02 am |
|
|
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
|
Re: Barcode Decoder Source Code |
Posted: Thu Feb 16, 2006 10:12 am |
|
|
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
|
|
Posted: Thu Feb 16, 2006 12:36 pm |
|
|
ChingB has not posted on the forum for 6 months. He has probably
left the forum. |
|
|
chingB
Joined: 29 Dec 2003 Posts: 81
|
|
Posted: Fri Mar 31, 2006 12:23 am |
|
|
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. |
|
|
|
|
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
|