iZsh fail0verflow / Mbed 2 deprecated BarcodeLED

Dependencies:   mbed

BarcodeLED.cpp

Committer:
iZsh
Date:
2010-09-13
Revision:
0:3b5e1025cbd6

File content as of revision 0:3b5e1025cbd6:

/* Copyright (c) 2010 iZsh - izsh at fail0verflow.com
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#include "BarcodeLED.h"

const char * BarcodeLED::m_Barcode39[] = {
  "1113313111", "3113111131", "1133111131", "3133111111", "1113311131", "3113311111", "1133311111",
  "1113113131", "3113113111", "1133113111", "3111131131", "1131131131", "3131131111", "1111331131",
  "3111331111", "1131331111", "1111133131", "3111133111", "1131133111", "1111333111", "3111111331",
  "1131111331", "3131111311", "1111311331", "3111311311", "1131311311", "1111113331", "3111113311",
  "1131113311", "1111313311", "3311111131", "1331111131", "3331111111", "1311311131", "3311311111",
  "1331311111", "1311113131", "3311113111", "1331113111", "1313131111", "1313111311", "1311131311",
  "1113131311", "1311313111"
};

const char * BarcodeLED::m_Barcode128[] = {
  "212222", "222122", "222221", "121223", "121322", "131222", "122213", "122312", "132212",
  "221213", "221312", "231212", "112232", "122132", "122231", "113222", "123122", "123221",
  "223211", "221132", "221231", "213212", "223112", "312131", "311222", "321122", "321221",
  "312212", "322112", "322211", "212123", "212321", "232121", "111323", "131123", "131321",
  "112313", "132113", "132311", "211313", "231113", "231311", "112133", "112331", "132131",
  "113123", "113321", "133121", "313121", "211331", "231131", "213113", "213311", "213131",
  "311123", "311321", "331121", "312113", "312311", "332111", "314111", "221411", "431111",
  "111224", "111422", "121124", "121421", "141122", "141221", "112214", "112412", "122114",
  "122411", "142112", "142211", "241211", "221114", "413111", "241112", "134111", "111242",
  "121142", "121241", "114212", "124112", "124211", "411212", "421112", "421211", "212141",
  "214121", "412121", "111143", "111341", "131141", "114113", "114311", "411113", "411311",
  "113141", "114131", "311141", "411131", "211412", "211214", "211232", "2331112"
};

BarcodeLED::BarcodeLED(const PinName Led, const CodeType Codetype, const int BaseDelay)
 : m_Led(DigitalOut(Led)), m_Codetype(Codetype), m_BaseDelay(BaseDelay), m_Verbose(false)
{
    m_Led = 1;
}
    
BarcodeLED::CodeType BarcodeLED::GetCodetype()
{
    return m_Codetype;
}

void BarcodeLED::SetCodetype(const CodeType Codetype)
{
    m_Codetype = Codetype;
}

int BarcodeLED::GetBaseDelay()
{
    return m_BaseDelay;
}

void BarcodeLED::SetBaseDelay(const int BaseDelay)
{
    m_BaseDelay = BaseDelay;
}

int BarcodeLED::GetVerbose()
{
    return m_Verbose;
}

void BarcodeLED::SetVerbose(const bool Verbose)
{
    m_Verbose = Verbose;
}

void BarcodeLED::Emit(const char Str[])
{
    switch (m_Codetype) {
    case Code128a:
    case Code128b:
    case Code128c:
        EmitCode128(Str);
        break;
    case Code39:
    default:
        EmitCode39(Str);
        break;
    }
}

void BarcodeLED::EmitCode39(const char Str[])
{
    if (m_Verbose)
        printf("sending \"%s\"\r\n", Str);
    // Let's build a sequence string
    // We do that (instead of sending the chars on the fly
    // because that's probably better timing-wise (not relying
    // on inlining) and because it gets easier that way to reverse
    // the sequence (to increase reliabilty)
    int len = strlen(Str);
    // Reserve the memory on the stack. Hopefully no one will
    // call this function with an insane string length
    int size = (len + 2) * 10 + 1; // |start|seq|stop|null|
    char seq[size];
    memset(seq, '\0', size);
    // And build the seq
    strncat(seq, "1311313111", size - 1); // Code39 start
    for (int i = 0; i < len; ++i)
        strncat(seq, m_Barcode39[ASCII2Code39(Str[i])], size - (i + 1) * 10 - 1);
    strncat(seq, "1311313111", size - (len + 1) * 10 - 1); // Code39 stop
    if (m_Verbose)
        printf("=> %s\r\n", seq);
    
    // Emit
    m_Led = 1;
    wait_us(m_BaseDelay * 100); // long whitespace
    FlashSeq(seq);              // Seq
    m_Led = 1;
    wait_us(m_BaseDelay * 25);  // short whitespace
    FlashSeq(RevStr(seq));      // Rev Seq
    m_Led = 1;
    wait_us(m_BaseDelay * 100); // long whitespace
}

void BarcodeLED::EmitCode128(const char Str[])
{
    if (m_Verbose)
        printf("sending \"%s\"\r\n", Str);
    int len = strlen(Str);
    int size = len * 6 + 6 * 2 + 7 + 1; // |start|seq|checksum|stop|null|
    char seq[size];
    memset(seq, '\0', size);
    // build the seq
    strncat(seq, m_Barcode128[m_Codetype], size - 1); // Code128 start
    for (int i = 0; i < len; ++i)
        strncat(seq, m_Barcode128[ASCII2Code128(Str[i])], size - (i + 1) * 6 - 1);
    strncat(seq, m_Barcode128[Code128Checksum(Str)],  size - (len + 1) * 6 - 1);
    strncat(seq, "2331112", size - (len + 2) * 6 - 1); // Code128 stop
    if (m_Verbose)
        printf("=> %s\r\n", seq);
    
    // Emit
    m_Led = 1;
    wait_us(m_BaseDelay * 100); // long whitespace
    FlashSeq(seq);              // Seq
    m_Led = 1;
    wait_us(m_BaseDelay * 25);  // short whitespace
    FlashSeq(RevStr(seq));      // Rev Seq
    m_Led = 1;
    wait_us(m_BaseDelay * 100); // long whitespace
}

// Convert an ASCII code to Code39
// It doesn't support the full ascii table yet
// That would need to use a sequence of two Code39 for that
// See http://en.wikipedia.org/wiki/Code_39
int BarcodeLED::ASCII2Code39(const char C)
{
    if (C >= '0' && C <= '9')
        return C - '0';
    // Case is ignored for now
    if (C >= 'A' && C <= 'Z')
        return C - 55;
    if (C >= 'a' && C <= 'z')
        return C - 87;
    // Punctuation and alike
    switch (C) {
    case '-':
        return 36;
    case '.':
        return 37;
    case ' ':
        return 38;
    case '$':
        return 39;
    case '/':
        return 40;
    case '+':
        return 41;
    case '%':
        return 42;
    case '*':
        return 43;
    }
    return 0;
}

int BarcodeLED::ASCII2Code128(const char C)
{
    if (C == ' ')
        return 0;
    if (C >= 33 && C <= 126)
        return C - 32;   
    if (C >= 145)
        return C - 50;
    if (C <= 31)        // Code128a
        return C + 64;
    return 0;
}

char * BarcodeLED::RevStr(char Str[])
{
    int len = strlen(Str);
    int s = 0;
    int e = len - 1;
    while (s < e) {
        char c = Str[s];
        Str[s] = Str[e];
        Str[e] = c;
        ++s;
        --e;
    }
    return Str;
}

void BarcodeLED::FlashSeq(const char Seq[])
{
    int b = 0;
    for (int i = 0; Seq[i] != '\0'; ++i) {
        m_Led = b;
        wait_us(m_BaseDelay * (Seq[i] - '0'));
        b = !b;
    }
}

int BarcodeLED::Code128Checksum(const char Str[])
{
  long checksum = m_Codetype;
  for (int i = 0; Str[i] != '\0'; ++i)
    checksum += (i + 1) * ASCII2Code128(Str[i]);
  return checksum % 103;
}