Screen won't update until serial data has stopped coming in. - Kotlin

Viewed 128

I have a kotlin app that has 4 gauges and about 120 textView numeric values (making a digital dash) and a serial adaptor that receives a data stream then decodes it and displays it, then gets more data and repeats. The problem is the display never updates until the serial stream is stopped. I have flow control but, can't figure out how to determine when the screen has been updated or insert a delay for screen to catch up. Thread.sleep() does not work as it seems to stop everything, so does running a counter up to 100 million or billion. Using Mik3y serial library. Using felHR85 the screen worked but, flow control did not. I have tried using SerialInputOutputManager to get interupts when new data arrives but, screen still does not seem to have enough time to update. Using a Samsung Tab A 10.1 which is on the lower end but, should have enough power on Android 10 (Sdk Ver 30) Any thoughts? Best Regards, Blake Here is the read function, I think you are right, putting this on another thread would probably help, I am not 100% how to do that and pass the array buffer (rsdash is a Byte array of 8196) between the threads. I am not sure how to setup the thread also.

            fun receive(count: Int, timeout: Int): Int {
                _serial.setRTS(true)
                val startTime = System.currentTimeMillis()
                val buffer = ByteArray(8196)
                readBytes = 0
                try {
                    while (readBytes <= count) {
                        val lend = _serial.read(buffer, timeout)
                        for (i in 0 until lend) {
                            rsdash[i + readBytes] = buffer[i]
                        }
                        readBytes = readBytes + lend
                        if (readBytes >= count) {
                            _serial.setRTS(false)
                            //if(count==387){display(rsdash)}
                            return readBytes
                        }

                        val duration = System.currentTimeMillis() - startTime
                        if (duration > timeout) {
                            _serial.setRTS(false)
                            break
                        }
                    }

                    _serial.setRTS(false)
                    return readBytes
                } catch (e: IOException) {
                    _serial.setRTS(false)
                    return 0
                }
        }
// This code is not working, (no interupt, I assume) I am calling Receive() from the main program
        val mListener: SerialInputOutputManager.Listener =
            object : SerialInputOutputManager.Listener {

                override fun onNewData(data: ByteArray) {
                    len = receive(387, 400)
                    _serial.write("0x52".toByteArray(), 2)
                    if (len == 387) {
                        chksum = 0
                        for (i in 0 until 384) chksum = chksum + (rsdash[i].toInt() and 0xFF)
                        chksum = (chksum and 0xFFFF)
                        val chktst =
                            (rsdash[385].toInt() and 0xFF shl 8 or (rsdash[384].toInt() and 0xFF)).toInt()
                        if (chksum == chktst) {
                            ++cnt
                            display(rsdash)
                            Air2.setText(cnt.toString())
                            LED.setTextColor(Color.parseColor("#FF00FF"))
                        } else {
                            _serial.purgeHwBuffers(true, true)
//                        display(rsdash)
                            LED.setTextColor(Color.parseColor("#00FFFF"))
                            //                        _serial.purgeHwBuffers(true, true)
                        }
                    }
                _serial.setRTS(true)
                }
                override fun onRunError(e: Exception) {
                    _serial.purgeHwBuffers(true, true)
                    _serial.setRTS(true)
                }
            }

//this is automatically connecting serial port either, I am calling con=connect() from main program also

broadcastReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        if (intent.action == INTENT_ACTION_GRANT_USB) {
            usbPermission = if (intent.getBooleanExtra(
                    UsbManager.EXTRA_PERMISSION_GRANTED,
                    false
                )
            ) UsbPermission.Granted else UsbPermission.Denied
            con=connect()
        }
    }
}

// Here is the code in the "main" that is working. As soon as the for loop is completed the screen updates. Everything look good on the scope, all checksums pass.

        if(con==false){con=connect()}
        if (con == true) {
            if (_connected == true) {

                for (i in 0 until 200) {
//                    _serial.setRTS(true)
                len = receive(387, 400)
                _serial.write("0x52".toByteArray(), 2)
                if (len == 387) {
                    chksum = 0
                    for (i in 0 until 384) chksum = chksum + (rsdash[i].toInt() and 0xFF)
                    chksum = (chksum and 0xFFFF)
                    val chktst =
                        (rsdash[385].toInt() and 0xFF shl 8 or (rsdash[384].toInt() and 0xFF)).toInt()
                    if (chksum == chktst) {
                        ++cnt
                        display(rsdash)
                        Air2.setText(cnt.toString())
                        LED.setTextColor(Color.parseColor("#FF00FF"))
                    } else {
                        _serial.purgeHwBuffers(true, true)
//                        display(rsdash)
                        LED.setTextColor(Color.parseColor("#00FFFF"))
                        //                        _serial.purgeHwBuffers(true, true)
                    }
                }


//The display function is long here are all the values on the display if that helps
        val EgtA = findViewById<ProgressBar>(R.id.EgtA)
        val EgtB = findViewById<ProgressBar>(R.id.EgtB)
        val EgtC = findViewById<ProgressBar>(R.id.EgtC)
        val EgtD = findViewById<ProgressBar>(R.id.EgtD)
        val EgtE = findViewById<ProgressBar>(R.id.EgtE)
        val EgtF = findViewById<ProgressBar>(R.id.EgtF)
        val EgtG = findViewById<ProgressBar>(R.id.EgtG)
        val EgtH = findViewById<ProgressBar>(R.id.EgtH)
        val EgtAN = findViewById<TextView>(R.id.EgtAN)
        val EgtBN = findViewById<TextView>(R.id.EgtBN)
        val EgtCN = findViewById<TextView>(R.id.EgtCN)
        val EgtDN = findViewById<TextView>(R.id.EgtDN)
        val EgtEN = findViewById<TextView>(R.id.EgtEN)
        val EgtFN = findViewById<TextView>(R.id.EgtFN)
        val EgtGN = findViewById<TextView>(R.id.EgtGN)
        val EgtHN = findViewById<TextView>(R.id.EgtHN)
        val O2A = findViewById<ProgressBar>(R.id.O2A)
        val O2B = findViewById<ProgressBar>(R.id.O2B)
        val O2C = findViewById<ProgressBar>(R.id.O2C)
        val O2D = findViewById<ProgressBar>(R.id.O2D)
        val O2E = findViewById<ProgressBar>(R.id.O2E)
        val O2F = findViewById<ProgressBar>(R.id.O2F)
        val O2G = findViewById<ProgressBar>(R.id.O2G)
        val O2H = findViewById<ProgressBar>(R.id.O2H)
        val O2AN = findViewById<TextView>(R.id.O2AN)
        val O2BN = findViewById<TextView>(R.id.O2BN)
        val O2CN = findViewById<TextView>(R.id.O2CN)
        val O2DN = findViewById<TextView>(R.id.O2DN)
        val O2EN = findViewById<TextView>(R.id.O2EN)
        val O2FN = findViewById<TextView>(R.id.O2FN)
        val O2GN = findViewById<TextView>(R.id.O2GN)
        val O2HN = findViewById<TextView>(R.id.O2HN)
        val CFA = findViewById<TextView>(R.id.CFA)
        val CFB = findViewById<TextView>(R.id.CFB)
        val CFC = findViewById<TextView>(R.id.CFC)
        val CFD = findViewById<TextView>(R.id.CFD)
        val CFE = findViewById<TextView>(R.id.CFE)
        val CFF = findViewById<TextView>(R.id.CFF)
        val CFG = findViewById<TextView>(R.id.CFG)
        val CFH = findViewById<TextView>(R.id.CFH)
        val Pr1 = findViewById<TextView>(R.id.Pr1)
        val Pr2 = findViewById<TextView>(R.id.Pr2)
        val Pr3 = findViewById<TextView>(R.id.Pr3)
        val Pr4 = findViewById<TextView>(R.id.Pr4)
        val Pr5 = findViewById<TextView>(R.id.Pr5)
        val throt = findViewById<ProgressBar>(R.id.throt)
        val Throt = findViewById<TextView>(R.id.Throt)
        val Flbs = findViewById<TextView>(R.id.Flbs)
        val Afl = findViewById<TextView>(R.id.Afl)
        val Tim = findViewById<TextView>(R.id.Tim)
        val tach = findViewById<Gauge>(R.id.tach)
        val fuel = findViewById<Gauge>(R.id.fuel)
        val Inj = findViewById<TextView>(R.id.Inj)
        val oil = findViewById<Gauge>(R.id.oil)
        val eng = findViewById<Gauge>(R.id.eng)
        val Batt = findViewById<TextView>(R.id.Batt)
        val O2v = findViewById<TextView>(R.id.O2v)
        val Map = findViewById<TextView>(R.id.Map)
        val Mat = findViewById<TextView>(R.id.Mat)
        val Baro = findViewById<TextView>(R.id.Baro)
        val Air = findViewById<TextView>(R.id.Air)
        val Air2 = findViewById<TextView>(R.id.Air2)
        val CF = findViewById<TextView>(R.id.CF)
        val TO2 = findViewById<TextView>(R.id.TO2)
        val Oilt = findViewById<TextView>(R.id.Oilt)
        val Trnt = findViewById<TextView>(R.id.Trnt)
        val TTL = findViewById<TextView>(R.id.TTL)
        val TTR = findViewById<TextView>(R.id.TTR)
        val Cjl = findViewById<TextView>(R.id.Cjl)
        val Cjr = findViewById<TextView>(R.id.Cjr)
        val Cjs = findViewById<TextView>(R.id.Cjs)
        val Sp1 = findViewById<TextView>(R.id.Sp1)
        val Sp2 = findViewById<TextView>(R.id.Sp2)
        val Sp3 = findViewById<TextView>(R.id.Sp3)
        val Sp4 = findViewById<TextView>(R.id.Sp4)
        val Sp5 = findViewById<TextView>(R.id.Sp5)
        val Xa = findViewById<TextView>(R.id.Xa)
        val Ya = findViewById<TextView>(R.id.Ya)
        val Za = findViewById<TextView>(R.id.Za)
1 Answers

I am not sure if I did this completely right but, it is working and it seems to have put the serial receiver on a separate thread. Here is the code for reference.

        fun connect(): Boolean {
            val drivers = UsbSerialProber.getDefaultProber().findAllDrivers(_usbManager)
            if (drivers.isEmpty()) {
                return false
            }

            val driver = drivers[0]
            val _connection = _usbManager.openDevice(driver.device)
            if (_connection == null) {
                _connected = false
                return false
            }

            val port = driver.ports[0]
            if (port == null) {
                _connected = false
                return false
            }

            try {
                port.open(_connection)
                port.setParameters(
                    115200,
                    8,
                    UsbSerialPort.STOPBITS_1,
                    UsbSerialPort.PARITY_NONE
                )
                port.purgeHwBuffers(true, true)
                _serial = port
                _connected = true

//                if (withIoManager) {
//                    usbIoManager = SerialInputOutputManager(usbSerialPort)
//                    Executors.newSingleThreadExecutor().submit(usbIoManager)
//                }
                //usbIoManager = SerialInputOutputManager(_serial,this)
                usbIoManager = SerialInputOutputManager(_serial, mListener)
                Executors.newSingleThreadExecutor().submit(usbIoManager)
//                val submit = Executors.newSingleThreadExecutor().submit(usbIoManager)
//                Executors.newSingleThreadExecutor().asCoroutineDispatcher(usbIoManager)

                _serial.setRTS(true)
                return true

            } catch (e: IOException) {
                //e.printStackTrace()

                if(_connected==true){port.close()}
                _connected = false
                return false
            }
        }
//        mainLooper = Handler(Looper.getMainLooper())

        broadcastReceiver = object : BroadcastReceiver() {
            override fun onReceive(context: Context, intent: Intent) {
                if (intent.action == INTENT_ACTION_GRANT_USB) {
                    usbPermission = if (intent.getBooleanExtra(
                            UsbManager.EXTRA_PERMISSION_GRANTED,
                            false
                        )
                    ) UsbPermission.Granted else UsbPermission.Denied
                    con=connect()
                }
            }
        }
        //mainLooper = Handler(Looper.getMainLooper())
Related