diff --git a/src/barcodescanner/config.py b/src/barcodescanner/config.py index b6fa8ff..2fc2fde 100644 --- a/src/barcodescanner/config.py +++ b/src/barcodescanner/config.py @@ -37,11 +37,12 @@ UART_ID = 0 # TX/RX: UART 0: 0/1, 12/13, or 16/17; UART 1: 4/5 or 8/9 UART_TX_PIN=0 UART_RX_PIN=1 +BUZZER_PWM_PIN = 11 # Pin for passive buzzer PWM TRIGGER_BUTTON_PIN = 12 # Pin to read for scan trigger button, connect trigger button between this and ground TRIGGER_PIN = 13 # Pin that connects to the scan module's trigger line, pulls the line low while the user is pressing the trigger button UP_BUTTON_PIN = 14 # Pin to read for navigation up button DOWN_BUTTON_PIN = 15 # Pin to read for navigation down button -LED_PIN = "LED" # 3 in prod +LED_PIN = 3 # "LED" for testing, 3 for prod FIRMWARE_VERSION = "0.0.1" # @@ -49,7 +50,7 @@ FIRMWARE_VERSION = "0.0.1" # SCAN_GAP_MS = 50 # Amount of time to wait for more characters from the scan engine before sending a barcode MAX_BARCODE_LENGTH = 8192 # Barcodes longer than this from the scan engine are assumed to be a glitch -TESTMODE = True # Sends a simulated barcode scan every 5 seconds +TESTMODE = False # Sends a simulated barcode scan every 5 seconds # # USB configuration diff --git a/src/barcodescanner/feedback.py b/src/barcodescanner/feedback.py index ec2111b..67deddc 100644 --- a/src/barcodescanner/feedback.py +++ b/src/barcodescanner/feedback.py @@ -30,12 +30,77 @@ # WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF # THE POSSIBILITY OF SUCH DAMAGE. -from machine import Pin -from time import sleep_us +from machine import Pin, PWM +import machine +from time import sleep_us, sleep_ms import config from oledscreen import iconDisplay, centerText +import _thread onboardLED = Pin(config.LED_PIN, Pin.OUT) +buzzerPin = PWM(Pin(config.BUZZER_PWM_PIN)) +ledSequence = [] +ledLock = _thread.allocate_lock() + +# Run LED on the second core so it doesn't slow down the main process + +def ledThreadFn(): + global feedbackType, ledSequence + while True: + ledLock.acquire() + if not ledSequence: + ledLock.release() + sleep_ms(1) + continue + seq = ledSequence + ledSequence = [] + ledLock.release() + for speed in seq: + pulseLED(speed) + + +ledThread = None + +# Run in main.py during boot +def createLEDThread(): + global ledThread + ledThread = _thread.start_new_thread(ledThreadFn, ()) + +def doFeedback(mode): + global ledSequence + if mode == "SCAN": + ledLock.acquire() + ledSequence = ["fast"] + ledLock.release() + passiveBuzzer(1047, 100) + elif mode == "OK": + ledLock.acquire() + ledSequence = ["fast"] + ledLock.release() + passiveBuzzer(1175, 100) + elif mode == "ERR": + ledLock.acquire() + ledSequence = ["fast", "fast", "fast"] + ledLock.release() + passiveBuzzer(440, 100) + sleep_ms(50) + passiveBuzzer(440, 100) + sleep_ms(50) + passiveBuzzer(440, 100) + elif mode == "POW": + ledLock.acquire() + ledSequence = ["normal"] + ledLock.release() + passiveBuzzer(880, 100) + passiveBuzzer(988, 100) + passiveBuzzer(1047, 100) + elif mode == "NAF": + ledLock.acquire() + ledSequence = ["normal", "fast", "fast", "normal"] + ledLock.release() + passiveBuzzer(440, 100) + passiveBuzzer(494, 100) + passiveBuzzer(440, 200) # Pulse the LED on and off with brightness fade def pulseLED(speed): @@ -58,24 +123,17 @@ def pulseLED(speed): onboardLED.off() sleep_us(i) +def passiveBuzzer(frequency, duration): + global buzzerPin + buzzerPin.duty_u16(int(65536*0.2)) + buzzerPin.freq(frequency) + sleep_ms(duration) + buzzerPin.duty_u16(int(0)) + def firmwareUpdateMessage(): centerText("Firmware Update", False, True) -def feedbackBuzzer(feedback): - if feedback == "OK": - iconDisplay("OK") - pulseLED("fast") - elif feedback == "ERR": - iconDisplay("ERR") - pulseLED("fast") - pulseLED("fast") - pulseLED("fast") - elif feedback == "POW": +def feedbackBuzzer(feedback, onMain = False): + if feedback == "POW": iconDisplay("POW") - #pulseLED("normal") - elif feedback == "NAF": - iconDisplay("NAF") - pulseLED("normal") - pulseLED("fast") - pulseLED("fast") - pulseLED("normal") + doFeedback(feedback) diff --git a/src/barcodescanner/main.py b/src/barcodescanner/main.py index a9dc99d..cadcaa6 100644 --- a/src/barcodescanner/main.py +++ b/src/barcodescanner/main.py @@ -31,7 +31,7 @@ # THE POSSIBILITY OF SUCH DAMAGE. -from sys import stdin, exit +from sys import stdin, exit, print_exception import machine from machine import Pin, USBDevice, UART from utime import sleep, sleep_ms, sleep_us @@ -41,7 +41,7 @@ import time from config import * from oledscreen import bootDisplay, clearDisplay, brightDisplay, mainDisplay, centerText from scannerusb import initUSBHID, createAndSendBarcodeReports -from feedback import feedbackBuzzer +from feedback import feedbackBuzzer, createLEDThread from scanmode import isScanInhibited, setModeID, getCurrentModeID, processNewListUSBReport from watchdog import startwatchdog, feedwatchdog @@ -92,13 +92,26 @@ menuUpButton.irq(handler=menuUpButtonHandler, trigger=Pin.IRQ_FALLING) menuDownButton.irq(handler=menuDownButtonHandler, trigger=Pin.IRQ_FALLING) # +# Send scan engine configuration commands over UART # -# -# TODO: Send scan engine configuration commands over UART -# -# -# +uart.write(b'\x7E\x00\x08\x01\x00\xD9\x50\xAB\xCD') # Restore factory defaults +uart.write(b'\x7E\x00\x08\x01\x00\x00\xC4\xAB\xCD') # 11000100 (LED settings) +uart.write(b'\x7E\x00\x08\x01\x00\x01\x90\xAB\xCD') # 10010000 (trigger settings) +uart.write(b'\x7E\x00\x08\x01\x00\x03\x03\xAB\xCD') # 00000011 (setup barcode settings) +uart.write(b'\x7E\x00\x08\x01\x00\x05\x05\xAB\xCD') # 500ms timeout between decodes of same barcode +uart.write(b'\x7E\x00\x08\x01\x00\x07\x00\xAB\xCD') # Disable deep sleep mode +uart.write(b'\x7E\x00\x08\x01\x00\x0D\x00\xAB\xCD') # Disable invoicing and virtual keyboard, set TTL232 output +uart.write(b'\x7E\x00\x08\x01\x00\x16\x01\xAB\xCD') # Try harder to decode bad barcodes +uart.write(b'\x7E\x00\x08\x01\x00\x17\x00\xAB\xCD') # Disable code128 prefix and GS replacement +uart.write(b'\x7E\x00\x08\x01\x00\x18\x1D\xAB\xCD') # Set GS replacement char to GS char just in case +uart.write(b'\x7E\x00\x08\x01\x00\x2C\x02\xAB\xCD') # Enable all symbologies +uart.write(b'\x7E\x00\x08\x01\x00\x33\x41\xAB\xCD') # Disable parentheses on Code128 AI, enable Code128 +uart.write(b'\x7E\x00\x08\x01\x00\x3F\x61\xAB\xCD') # Disable parentheses on QR/DataMatrix AI, enable QR +uart.write(b'\x7E\x00\x08\x01\x00\xD9\x56\xAB\xCD') # Save as custom defaults + +feedwatchdog() +createLEDThread() feedwatchdog() feedbackBuzzer("POW") feedwatchdog() @@ -155,7 +168,7 @@ while True: uartBuffer.extend(data) lastBufferActivity = time.ticks_ms() if len(uartBuffer) > MAX_BARCODE_LENGTH: - uartBuffer.clear() + uartBuffer[:] = b'' # clear buffer bufferOverflow = True lastBufferActivity = None @@ -163,8 +176,8 @@ while True: if lastBufferActivity is not None and time.ticks_diff(time.ticks_ms(), lastBufferActivity) > SCAN_GAP_MS: if not isScanInhibited() and uartBuffer and not bufferOverflow: createAndSendBarcodeReports(bytes(uartBuffer)) - feedbackBuzzer("OK") - uartBuffer.clear() + feedbackBuzzer("SCAN", True) + uartBuffer[:] = b'' # clear buffer lastBufferActivity = None bufferOverflow = False @@ -172,7 +185,7 @@ while True: if TESTMODE and time.ticks_diff(time.ticks_ms(), lastTestSend) > 5000: createAndSendBarcodeReports(b'test barcode 12345') - feedbackBuzzer("OK") + feedbackBuzzer("SCAN") lastTestSend = time.ticks_ms() feedwatchdog() @@ -185,5 +198,5 @@ while True: machine.idle() except Exception as e: # Dump exceptions over serial for debugging - print(e) + print_exception(e) machine.reset() diff --git a/src/barcodescanner/scannerusb.py b/src/barcodescanner/scannerusb.py index a9c289f..6ec6a86 100644 --- a/src/barcodescanner/scannerusb.py +++ b/src/barcodescanner/scannerusb.py @@ -39,6 +39,7 @@ from feedback import feedbackBuzzer, firmwareUpdateMessage from watchdog import feedwatchdog import time from sys import stdout +from utime import sleep_ms usbinterface = None @@ -225,7 +226,7 @@ class USBHIDInterface(HIDInterface): while self.busy(): # Wait for queue to open up, but drop this report on timeout # because the host isn't paying attention to us and this will deadlock if we wait forever - if time.ticks_diff(time.ticks_ms(), start) > 5: + if time.ticks_diff(time.ticks_ms(), start) > 10: return False machine.idle() self.send_report(data) @@ -250,12 +251,17 @@ def createAndSendBarcodeReports(barcodeData): global usbinterface chunks = split(barcodeData, 56) for i, chunk in enumerate(chunks): + isLastReport = len(chunks) - 1 == i lastByte = b'\x01' - if len(chunks) - 1 == i: + if isLastReport: lastByte = b'\x00' report = b'\x02' + bytes([len(chunk)]) + b'\x00\x00\x00' + pad_data(chunk, 56) + b'\x00' + bytes([getCurrentModeID()]) + lastByte if USBHID_ENABLED: - if not usbinterface.send_data(report): + if usbinterface.send_data(report): + if not isLastReport: + sleep_ms(50) # Wait a few milliseconds before sending the next report so it won't get dropped + print(report) + else: break # Stop sending barcode over USB, the host didn't get this chunk but it might get the next and only have half a barcode feedwatchdog() # Write barcode data to serial out for non-HID system compatibility