Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: BarcodeReader_F103
code39.c
00001 /*------------------------------------------------------------------------ 00002 * Copyright 2008-2009 (c) Jeff Brown <spadix@users.sourceforge.net> 00003 * 00004 * This file is part of the ZBar Bar Code Reader. 00005 * 00006 * The ZBar Bar Code Reader is free software; you can redistribute it 00007 * and/or modify it under the terms of the GNU Lesser Public License as 00008 * published by the Free Software Foundation; either version 2.1 of 00009 * the License, or (at your option) any later version. 00010 * 00011 * The ZBar Bar Code Reader is distributed in the hope that it will be 00012 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty 00013 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU Lesser Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser Public License 00017 * along with the ZBar Bar Code Reader; if not, write to the Free 00018 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, 00019 * Boston, MA 02110-1301 USA 00020 * 00021 * http://sourceforge.net/projects/zbar 00022 *------------------------------------------------------------------------*/ 00023 00024 #include "../config.h" 00025 #include <string.h> /* memmove */ 00026 00027 #ifdef ENABLE_CODE39 00028 00029 #include <zbar.h> 00030 #include "../decoder.h" 00031 00032 #ifdef DEBUG_CODE39 00033 # define DEBUG_LEVEL DEBUG_CODE39 00034 #endif 00035 #include "../debug.h" 00036 00037 #define NUM_CHARS (0x2c) 00038 00039 static const unsigned char code39_hi[32] = { 00040 0x80 | 0x00, /* 2 next */ 00041 0x40 | 0x02, /* 4 */ 00042 0x80 | 0x06, /* 2 next */ 00043 0xc0 | 0x08, /* 2 skip */ 00044 0x40 | 0x0a, /* 4 */ 00045 0x80 | 0x0e, /* 2 next */ 00046 0xc0 | 0x10, /* 2 skip */ 00047 0x00 | 0x12, /* direct */ 00048 00049 0x80 | 0x13, /* 2 next */ 00050 0xc0 | 0x15, /* 2 skip */ 00051 0x80 | 0x17, /* 2 next */ 00052 0xff, 00053 0xc0 | 0x19, /* 2 skip */ 00054 0x00 | 0x1b, /* direct */ 00055 0xff, 00056 0xff, 00057 00058 0x40 | 0x1c, /* 4 */ 00059 0x80 | 0x20, /* 2 next */ 00060 0xc0 | 0x22, /* 2 skip */ 00061 0x00 | 0x24, /* direct */ 00062 0x80 | 0x25, /* 2 next */ 00063 0xff, 00064 0x00 | 0x27, /* direct */ 00065 0xff, 00066 00067 0xc0 | 0x28, /* 2 skip */ 00068 0x00 | 0x2a, /* direct */ 00069 0xff, 00070 0xff, 00071 0x00 | 0x2b, /* direct */ 00072 0xff, 00073 0xff, 00074 0xff, 00075 }; 00076 00077 typedef struct char39_s { 00078 unsigned char chk, rev, fwd; 00079 } char39_t; 00080 00081 static const char39_t code39_encodings[NUM_CHARS] = { 00082 { 0x07, 0x1a, 0x20 }, /* 00 */ 00083 { 0x0d, 0x10, 0x03 }, /* 01 */ 00084 { 0x13, 0x17, 0x22 }, /* 02 */ 00085 { 0x16, 0x1d, 0x23 }, /* 03 */ 00086 { 0x19, 0x0d, 0x05 }, /* 04 */ 00087 { 0x1c, 0x13, 0x06 }, /* 05 */ 00088 { 0x25, 0x07, 0x0c }, /* 06 */ 00089 { 0x2a, 0x2a, 0x27 }, /* 07 */ 00090 { 0x31, 0x04, 0x0e }, /* 08 */ 00091 { 0x34, 0x00, 0x0f }, /* 09 */ 00092 { 0x43, 0x15, 0x25 }, /* 0a */ 00093 { 0x46, 0x1c, 0x26 }, /* 0b */ 00094 { 0x49, 0x0b, 0x08 }, /* 0c */ 00095 { 0x4c, 0x12, 0x09 }, /* 0d */ 00096 { 0x52, 0x19, 0x2b }, /* 0e */ 00097 { 0x58, 0x0f, 0x00 }, /* 0f */ 00098 { 0x61, 0x02, 0x11 }, /* 10 */ 00099 { 0x64, 0x09, 0x12 }, /* 11 */ 00100 { 0x70, 0x06, 0x13 }, /* 12 */ 00101 { 0x85, 0x24, 0x16 }, /* 13 */ 00102 { 0x8a, 0x29, 0x28 }, /* 14 */ 00103 { 0x91, 0x21, 0x18 }, /* 15 */ 00104 { 0x94, 0x2b, 0x19 }, /* 16 */ 00105 { 0xa2, 0x28, 0x29 }, /* 17 */ 00106 { 0xa8, 0x27, 0x2a }, /* 18 */ 00107 { 0xc1, 0x1f, 0x1b }, /* 19 */ 00108 { 0xc4, 0x26, 0x1c }, /* 1a */ 00109 { 0xd0, 0x23, 0x1d }, /* 1b */ 00110 { 0x03, 0x14, 0x1e }, /* 1c */ 00111 { 0x06, 0x1b, 0x1f }, /* 1d */ 00112 { 0x09, 0x0a, 0x01 }, /* 1e */ 00113 { 0x0c, 0x11, 0x02 }, /* 1f */ 00114 { 0x12, 0x18, 0x21 }, /* 20 */ 00115 { 0x18, 0x0e, 0x04 }, /* 21 */ 00116 { 0x21, 0x01, 0x0a }, /* 22 */ 00117 { 0x24, 0x08, 0x0b }, /* 23 */ 00118 { 0x30, 0x05, 0x0d }, /* 24 */ 00119 { 0x42, 0x16, 0x24 }, /* 25 */ 00120 { 0x48, 0x0c, 0x07 }, /* 26 */ 00121 { 0x60, 0x03, 0x10 }, /* 27 */ 00122 { 0x81, 0x1e, 0x14 }, /* 28 */ 00123 { 0x84, 0x25, 0x15 }, /* 29 */ 00124 { 0x90, 0x22, 0x17 }, /* 2a */ 00125 { 0xc0, 0x20, 0x1a }, /* 2b */ 00126 }; 00127 00128 static const unsigned char code39_characters[NUM_CHARS] = 00129 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%*"; 00130 00131 static inline unsigned char code39_decode1 (unsigned char enc, 00132 unsigned e, 00133 unsigned s) 00134 { 00135 unsigned char E = decode_e(e, s, 36); 00136 if(E > 7) 00137 return(0xff); 00138 enc <<= 1; 00139 if(E > 2) { 00140 enc |= 1; 00141 dprintf(2, "1"); 00142 } 00143 else 00144 dprintf(2, "0"); 00145 return(enc); 00146 } 00147 00148 static inline signed char code39_decode9 (zbar_decoder_t *dcode) 00149 { 00150 code39_decoder_t *dcode39 = &dcode->code39; 00151 00152 dprintf(2, " s=%d ", dcode39->s9); 00153 if(dcode39->s9 < 9) 00154 return(-1); 00155 00156 /* threshold bar width ratios */ 00157 unsigned char i, enc = 0; 00158 for(i = 0; i < 5; i++) { 00159 enc = code39_decode1(enc, get_width(dcode, i), dcode39->s9); 00160 if(enc == 0xff) 00161 return(-1); 00162 } 00163 zassert(enc < 0x20, -1, " enc=%x s9=%x\n", enc, dcode39->s9); 00164 00165 /* lookup first 5 encoded widths for coarse decode */ 00166 unsigned char idx = code39_hi[enc]; 00167 if(idx == 0xff) 00168 return(-1); 00169 00170 /* encode remaining widths (NB first encoded width is lost) */ 00171 for(; i < 9; i++) { 00172 enc = code39_decode1(enc, get_width(dcode, i), dcode39->s9); 00173 if(enc == 0xff) 00174 return(-1); 00175 } 00176 00177 if((idx & 0xc0) == 0x80) 00178 idx = (idx & 0x3f) + ((enc >> 3) & 1); 00179 else if((idx & 0xc0) == 0xc0) 00180 idx = (idx & 0x3f) + ((enc >> 2) & 1); 00181 else if(idx & 0xc0) 00182 idx = (idx & 0x3f) + ((enc >> 2) & 3); 00183 zassert(idx < 0x2c, -1, " idx=%x enc=%x s9=%x\n", idx, enc, dcode39->s9); 00184 00185 const char39_t *c = &code39_encodings[idx]; 00186 dprintf(2, " i=%02x chk=%02x c=%02x/%02x", idx, c->chk, c->fwd, c->rev); 00187 if(enc != c->chk) 00188 return(-1); 00189 00190 dcode39->width = dcode39->s9; 00191 return((dcode39->direction) ? c->rev : c->fwd); 00192 } 00193 00194 static inline signed char code39_decode_start (zbar_decoder_t *dcode) 00195 { 00196 code39_decoder_t *dcode39 = &dcode->code39; 00197 00198 signed char c = code39_decode9(dcode); 00199 if(c == 0x19) 00200 dcode39->direction ^= 1; 00201 else if(c != 0x2b) { 00202 dprintf(2, "\n"); 00203 return(ZBAR_NONE); 00204 } 00205 00206 /* check leading quiet zone - spec is 10x */ 00207 unsigned quiet = get_width(dcode, 9); 00208 if(quiet && quiet < dcode39->s9 / 2) { 00209 dprintf(2, " [invalid quiet]\n"); 00210 return(ZBAR_NONE); 00211 } 00212 00213 dcode39->element = 9; 00214 dcode39->character = 0; 00215 dprintf(1, " dir=%x [valid start]\n", dcode39->direction); 00216 return(ZBAR_PARTIAL); 00217 } 00218 00219 static inline void code39_postprocess (zbar_decoder_t *dcode) 00220 { 00221 code39_decoder_t *dcode39 = &dcode->code39; 00222 int i; 00223 if(dcode39->direction) { 00224 /* reverse buffer */ 00225 dprintf(2, " (rev)"); 00226 for(i = 0; i < dcode39->character / 2; i++) { 00227 unsigned j = dcode39->character - 1 - i; 00228 char code = dcode->buf[i]; 00229 dcode->buf[i] = dcode->buf[j]; 00230 dcode->buf[j] = code; 00231 } 00232 } 00233 for(i = 0; i < dcode39->character; i++) 00234 dcode->buf[i] = ((dcode->buf[i] < 0x2b) 00235 ? code39_characters[(unsigned)dcode->buf[i]] 00236 : '?'); 00237 dcode->buflen = i; 00238 dcode->buf[i] = '\0'; 00239 } 00240 00241 zbar_symbol_type_t _zbar_decode_code39 (zbar_decoder_t *dcode) 00242 { 00243 code39_decoder_t *dcode39 = &dcode->code39; 00244 00245 /* update latest character width */ 00246 dcode39->s9 -= get_width(dcode, 9); 00247 dcode39->s9 += get_width(dcode, 0); 00248 00249 if(dcode39->character < 0) { 00250 if(get_color(dcode) != ZBAR_BAR) 00251 return(ZBAR_NONE); 00252 dprintf(2, " code39:"); 00253 return((zbar_symbol_type_t)code39_decode_start(dcode)); 00254 } 00255 00256 if(++dcode39->element < 9) 00257 return(ZBAR_NONE); 00258 00259 dprintf(2, " code39[%c%02d+%x]", 00260 (dcode39->direction) ? '<' : '>', 00261 dcode39->character, dcode39->element); 00262 00263 if(dcode39->element == 10) { 00264 unsigned space = get_width(dcode, 0); 00265 if(dcode39->character && 00266 dcode->buf[dcode39->character - 1] == 0x2b) { /* STOP */ 00267 /* trim STOP character */ 00268 dcode39->character--; 00269 zbar_symbol_type_t sym = ZBAR_CODE39; 00270 00271 /* trailing quiet zone check */ 00272 if(space && space < dcode39->width / 2) { 00273 dprintf(2, " [invalid qz]\n"); 00274 sym = ZBAR_NONE; 00275 } 00276 else if(dcode39->character < CFG(*dcode39, ZBAR_CFG_MIN_LEN) || 00277 (CFG(*dcode39, ZBAR_CFG_MAX_LEN) > 0 && 00278 dcode39->character > CFG(*dcode39, ZBAR_CFG_MAX_LEN))) { 00279 dprintf(2, " [invalid len]\n"); 00280 sym = ZBAR_NONE; 00281 } 00282 else { 00283 /* FIXME checksum (needs config enable) */ 00284 code39_postprocess(dcode); 00285 dprintf(2, " [valid end]\n"); 00286 } 00287 dcode39->character = -1; 00288 if(!sym) 00289 dcode->lock = ZBAR_NONE; 00290 return(sym); 00291 } 00292 if(space > dcode39->width / 2) { 00293 /* inter-character space check failure */ 00294 dcode->lock = ZBAR_NONE; 00295 dcode39->character = -1; 00296 dprintf(2, " ics>%d [invalid ics]", dcode39->width); 00297 } 00298 dcode39->element = ZBAR_NONE; 00299 dprintf(2, "\n"); 00300 return(ZBAR_NONE); 00301 } 00302 00303 signed char c = code39_decode9(dcode); 00304 dprintf(2, " c=%d", c); 00305 00306 /* lock shared resources */ 00307 if(!dcode39->character && get_lock(dcode, ZBAR_CODE39)) { 00308 dcode39->character = -1; 00309 dprintf(1, " [locked %d]\n", dcode->lock); 00310 return(ZBAR_PARTIAL); 00311 } 00312 00313 if(c < 0 || 00314 ((dcode39->character >= BUFFER_MIN) && 00315 size_buf(dcode, dcode39->character + 1))) { 00316 dprintf(1, (c < 0) ? " [aborted]\n" : " [overflow]\n"); 00317 dcode->lock = ZBAR_NONE; 00318 dcode39->character = -1; 00319 return(ZBAR_NONE); 00320 } 00321 else { 00322 zassert(c < 0x2c, ZBAR_NONE, "c=%02x s9=%x\n", c, dcode39->s9); 00323 dprintf(2, "\n"); 00324 } 00325 00326 dcode->buf[dcode39->character++] = c; 00327 00328 return(ZBAR_NONE); 00329 } 00330 00331 #endif
Generated on Tue Jul 12 2022 21:31:48 by
1.7.2