decoding barcodes various approaches. decoding barcodes there are a number of ways of decoding the...

24
Decoding Barcodes Various approaches

Post on 22-Dec-2015

225 views

Category:

Documents


2 download

TRANSCRIPT

Decoding Barcodes

Various approaches

Decoding barcodes

• There are a number of ways of decoding the barcodes– The data can be polled– The data can be read on interrupt – The data can be sampled

Polling

• Repeatedly test the port B bit for state change, then – Store time value for the change

• Requires Port B set up and clock running

• Locks up the board, or risks data lose through multiple polling

• Data will require a lot of filtering

Port B Registers

Port B control Register (PBCNT) 0X100016 Set the port to specify the function of each pin – either dedicated special function or general purpose. CBN = 0 means general purpose: CBN =1 means dedicated. CB15 CB14 CB13 CB12 CB11 CB10 CB9 CB8 CB7 CB6 CB5 CB4 CB3 CB2 CB1 CB0 Port B Data Direction Register (PBDDR) 0X100018 Set whether a bit is an input or an output. DBN = 0 means input: DBN = 1 means output. DB15 DB14 DB13 DB12 DB11 DB10 DB9 DB8 DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0

Port B Data Register (PBDAT) 0X10001A Stores the logic state of the port. Reading an input pin will return its current logic state, writing to an output pin will set its state.

PB15 PB14 PB13 PB12 PB11 PB10 PB9 PB8 PB7 PB6 PB5 PB4 PB3 PB2 PB1 PB0

Minos code to program port B#include <adio.h> #include <stdio.h> #include <minos.h> #define WAND 9 //the 2nd bit on port B = 9 #define LED 8 //the 1st bit on port b =8 #define OFF 2 #define ON 3 main() { adioinit(); watchdog(OFF); //turn off watchdog outch(LED); // set up LED writech(LED,1); //turn LED on - ueful for debug! if ( inch(WAND) != -1 ) //make 9th bit (wand) input { while ( readch(WAND) != 0) //read transitions ; for ( ;; ) { if (readch(WAND) == 0 ) printf("off\n"); else printf("on\n"); delay(5); } } else printf("Error setting Channel 9 \n"); watchdog(ON); }

Program port B at low level#include <minos.h> #include <stdio.h> void i2set(void); main() { volatile unsigned short * Pbdat; int i; Pbdat = (unsigned short*) 0x10001a; i2set(); while (!(*Pbdat & 0x200)) ; while(!ready(0)) { if ( (*Pbdat & 0x200)) printf("pressed on \n"); else printf("pressed off \n"); } }

Program port B at low level// set up the second bit of port B to input // PBCNT = port b control PBDDR = port b data direction reg void i2set(void) { unsigned short *PBCNT ,*PBDDR, temp; PBCNT = (unsigned short *)0x100016; PBDDR = (unsigned short *)0x100018; temp = (unsigned short) *PBCNT; temp |= 0x02; *PBCNT = (unsigned short) temp; /* same as ....... #asm move.w $100016,D2 bset #9,D2 move.w D2,$100016 #endasm */ temp = (unsigned short )*PBDDR; /*clear port DDR to make pb9 input */ temp &= 0xfdff; *PBDDR = (unsigned short) temp; /*set port b control reg to input */ /* same as..... #asm move.w $100018,D2 bclr #10,D2 move.w D2,$100018 #endasm */ }

Timer RegistersTMR2 0x1000130 15 8 0 PRESCALER VALUE (PS7-0) CE1-CE0 OM ORI FRR ICLK1-0 RST TRR2 0x1000132 15 0 16-Bit Reference Compare Value REF15-0 TCR2 0x1000134 15 0 16-Bit Captured Counter Value REF15-0 TCN2 0x1000136 15 0 16-Bit Timer Counter Value REF15-0 TER2 0x1000139

7 0 Reserved REF CAP

Timer code

void timer(void) { unsigned short * Trr2; unsigned short * Tcn2; unsigned short * Tmr2; Tmr2 = (unsigned short *) 0x100130; Trr2 = (unsigned short *) 0x100132; Tcn2 = (unsigned short *) 0x100136; *Trr2 = (unsigned short) 0xffff; *Tcn2 = (unsigned short) 0x0000; *Tmr2 = (unsigned short) 0x000b; }

#include <minos.h> #include <stdio.h> #include <adio.h> unsigned short bns[60]; void i2set(void); void timer(void); main() { volatile unsigned short * Pbdat; volatile unsigned short * Tcnt2; int i, flag; char c; Tcnt2 = (unsigned short*) 0x100136; Pbdat = (unsigned short*) 0x10001a; i2set(); flag=i=0; while ( !(*Pbdat & 0x200)) ;// do nothing timer(); while ( i != 60 ) { while ( (*Pbdat & 0x200)) ;// do nothing bns[i++]= (unsigned short)*Tcnt2; timer(); while ( !(*Pbdat & 0x200)) ;// do nothing bns[i++]= (unsigned short)*Tcnt2; timer(); } for (i=0; i != 60 ; i++) { c = ((i % 4) == 0) ? '\n' : ' '; printf("%d is %x %c",i,bns[i],c ); } }

void i2set(void) { unsigned short *PBCNT; unsigned short *PBDDR; unsigned short status, temp; PBCNT = (unsigned short *)0x100016; PBDDR = (unsigned short *)0x100018; temp = (unsigned short )*PBDDR; /*clear port DDR to make pb9 input */ temp &= 0xfdff; *PBDDR = (unsigned short) temp; /*set port b control reg to input */ /* same as..... #asm move.w $100018,D2 bclr #10,D2 move.w D2,$100018 #endasm */ #asm move.w $100016,D2 bclr #9,D2 move.w D2,$100016 #endasm }

Interrupt driven code

• 2 possible sources for the interrupt– The bar code wand pin – Port B– The timer – Timer 2

• The timer is only really needed if you require a time out to abort the read

• Requires some careful setting up of the various peripherals and care with the order of the code

Interrupt driven code

• Uses the resources of the board very well

• Once implemented properly it is a very elegant and simple solution

• Will allow other activities to take place on the board

• Can generate noisy data

• Can be difficult to debug

Interrupt Code// example code for interrupt driven barcode input // inputs on the 9th bit of port b // timings saved for each transition // Craig 20/2/02 #include <minos.h> #include <stdio.h> #include <adio.h> #define NBARS 60 irqhandler oldTvec, oldI2vec; //prototypes void _interrupt wand(void); void _interrupt timeout(void); void i2set(void); void timer(void); void IRQstop( void ); unsigned short int bns[NBARS]; // bar code read array static int i=0; // global counter for array

// code to set up pin 9 of port B as input and generate interrupt order of settings is important! void i2set(void) { unsigned short *PBDDR, temp; PBDDR = (unsigned short *)0x100018; #asm /*set port b control reg to interrupt must be done first! */ move.w $100016,D2 bset #9,D2 move.w D2,$100016 /*set LICR for PB9 set to IPL 3, reset ints */ move.w $100020,D3 bclr #10,D3 bset #9,D3 bset #8,D3 bset #11,D3 move.w D3,$100020 #endasm temp = (unsigned short)*PBDDR; /*clear port DDR to make pb9 input */ temp &= 0xfdff; *PBDDR = (unsigned short) temp; /* same as.....#asm move.w $100018,D2 bclr #10,D2 move.w D2,$100018 #endasm */ oldI2vec = _getvect(0x43); /* save the old int2 vector */ _setvect(0x43,wand); }

// initilise timer 2, set up to generate interrupt on reaching reference // value 0xffff void timer(void) { unsigned short * Trr2; // timer reference register unsigned short * Tcn2; // timer control register unsigned short * Tmr2; // timer mode register unsigned short * Picr; // peripheral interrupt control register Tmr2 = (unsigned short *) 0x100130; Trr2 = (unsigned short *) 0x100132; Tcn2 = (unsigned short *) 0x100136; Picr = (unsigned short *) 0x100024; oldTvec = _getvect(0x4b); /* Save current handler address */ _setvect(0x4b,timeout); *Trr2 = (unsigned short) 0xffff; *Tcn2 = (unsigned short) 0x0000; *Tmr2 = (unsigned short) 0x801b; *Picr = *Picr | (unsigned short) 0x0300; }

// wand interrrupt handler. Catches interrupt from bar code transition // catches timer value into timings array. reset timer. clears interrupt // licr latched interrupt control register void _interrupt wand(void) { unsigned short * Tcn2; Tcn2 = (unsigned short *) 0x100136; bns[i++]= (unsigned short)*Tcn2; *Tcn2 =0; /* then clear int in Licr1 */ #asm move.w $100020,D3 bclr #10,D3 bset #9,D3 bset #8,D3 bset #11,D3 move.w D3,$100020 #endasm }

// clean up, stop timer, clear interrupts in LICR, reset port B and restore old isrs void IRQstop( void ) { unsigned short * Tmr2; Tmr2 = (unsigned short *) 0x100130; *Tmr2 = (unsigned short) 0; #asm move.w $100020,D3 bclr #10,D3 bclr #9,D3 bclr #8,D3 move.w D3,$100020 bset #11,D3 move.w D3,$100020 move.w $100016,D2 bclr #9,D2 move.w D2,$100016 #endasm _setvect(0x4b,oldTvec); _setvect(0x43,oldI2vec); } main() { int j; for (j=0;j != NBARS; j++) bns[j]=0; i2set(); timer(); while(i != NBARS) do nothing; IRQstop(); for (j=0;j != NBARS; j++) printf("%d read = %hu %c",j,bns[j], (j % 4) ? ' ' : '\n' ); }

// timeout interrupt - could terminate program, currently // just wiggles led & clears interrupt condition void _interrupt timeout(void) { unsigned char * Ter2; Ter2 = (unsigned char *) 0x100139; *Ter2 = (unsigned char) 0x02; // clear interrupt #asm //wiggle led move.w $100018,D3 bchg #8,D3 move.w D3,$100018 #endasm }

Coding using sampling

• This is an alternative interrupt driven method

• Rather than use the Port B interrupts it uses the timer to sample the Port B input

• Can use various settings for the timer

• The data read is just a count of 0s or 1s

Coding using sampling

• Allows flexibility in that sample rate is easy to change

• Only 1 source of interrupt – so is fairly simple

• Data read is very simple and easy to organise

Sampling Code#include <minos.h> #include <stdio.h> void i2set(void) { unsigned short *PBCNT; unsigned short *PBDDR; unsigned short status, temp;

PBCNT = (unsigned short *)0x100016; PBDDR = (unsigned short *)0x100018; temp = (unsigned short )*PBDDR; /*clear port DDR to make pb9 input */ temp &= 0xfdff; *PBDDR = (unsigned short) temp; /*set port b control reg to input */

/* same as..... #asm move.w $100018,D2 bclr #10,D2 move.w D2,$100018 move.w $100016,D2 bclr #9,D2 move.w D2,$100016 #endasm }

// initilise timer 2, set up to generate interrupt on reaching reference // value 0x???? void timer(void) { unsigned short * Trr2; // timer reference register unsigned short * Tcn2; // timer control register unsigned short * Tmr2; // timer mode register unsigned short * Picr; // peripheral interrupt control register Tmr2 = (unsigned short *) 0x100130; Trr2 = (unsigned short *) 0x100132; Tcn2 = (unsigned short *) 0x100136; Picr = (unsigned short *) 0x100024; //oldTvec = _getvect(0x4b); /* Save current handler address */ _setvect(0x4b,timeout); *Trr2 = (unsigned short) 0xf00; *Tcn2 = (unsigned short) 0x0000; *Tmr2 = (unsigned short) 0x801b; *Picr = *Picr | (unsigned short) 0x0300; }

void _interrupt timeout(void) { unsigned char * Ter2; volatile unsigned short * Pbdat; Pbdat = (unsigned short*) 0x10001a; Ter2 = (unsigned char *) 0x100139; i++; printf("%u\t", (*Pbdat & 0x200)); *Ter2 = (unsigned char) 0x02; // clear interrupt #asm //wiggle led move.w $100018,D3 bchg #8,D3 move.w D3,$100018 #endasm } main() { int j; i2set(); timer(); while (i != NOTRANS) ; IRQstop(); }