Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // 最大フレームサイズ
- private static final int READ_BUFFER_SIZE = 1600;
- // 最大キューサイズ
- private static final int MAX_QUEUE_SIZE = 4;
- // プールの初期サイズ
- private static final int INIT_POOL_SZ = 4:
- // 最大プールサイズ
- private static final int MAX_POOL_SZ = 8;
- // 最大リクエストサイズ
- private static final int MAX_REQUESTS = 4;
- // フレームデータプールを作る(リアローケーション防止のため)
- private final List<ByteBuffer> mPool = new ArrayList<ByteBuffer>(POOL_SZ);
- // FIFOのフレームデータキューを作る(なんでもいいけど普通はLinkedBlockingQueueを使う)
- private final LinkedBlockingQueue<ByteBuffer> mFrameQueue
- = new LinkedBlockingQueue<ByteBuffer>(MAX_QUEUE_SIZE);
- // プールの初期化
- private void initPool() {
- for(int i = 0; i < POOL_SZ; i++) {
- mPool.add(ByteBuffer.allocateDirect(READ_BUFFER_SIZE)
- .order(ByteOrder.nativeOrder()));
- }
- }
- private ByteBuffer obtain(final int sz) {
- ByteBuffer result = null;
- synchronized (mPool) {
- if (!mPool.isEmpty()) {
- result = mPool.remove(mPool.szie() - 1);
- }
- }
- if ((result == null) || (result.capacity() < sz)) {
- if (D) Log.w(TAG, "create ByteBuffer");
- result = ByteBuffer.allocateDirect(READ_BUFFER_SIZE)
- .order(ByteOrder.nativeOrder());
- }
- result.clear();
- return result;
- }
- private void recycle(@NonNull final ByteBuffer buf) {
- synchronized (mPool) {
- if (mPool.size() < MAX_POOL_SZ) {
- mPool.add(buf);
- }
- }
- }
- private void offer(@NonNull final ByteBuffer buffer) {
- if (!mFrameQueue.offer(buffer)) {
- if (D) Log.w(TAG, "frame queue is full, frame dropped");
- // 必要であれば、一番古いデータ=先頭を除去してから
- // 再度offerを試みるとよい
- }
- }
- ...
- private boolean queueRequest(@NonNull final UsbRequest request,
- final int read_sz) {
- boolean result = false;
- final ByteBuffer buf = obtain(read_sz);
- if (buf != null) {
- request.setClientData(buf);
- result = request.queue(buf, read_sz)) {
- }
- return result;
- }
- private class UsbReceiveThread extends Thread {
- private GraphDrawThread graphDrawThread;
- UsbReceiveThread() {
- super("UsbReceiveThread");
- initPool();
- graphDrawThread = new GraphDrawThread();
- }
- @Override
- public void run() {
- // この配列は必ずしもなくてもいい
- // その場合は先にgraphDrawThreadを起床しておいて
- // UsbRequestの生成, initialize, queueを1つのループ内で行う
- final UsbRequest requests[MAX_REQUESTS]
- = new UsbRequest[MAX_REQUESTS];
- for (int i = 0; i < MAX_REQUESTS; i++) {
- requests[i] = new UsbRequest();
- if (requests[i].initialize(deviceConnection, endPointRead)) {
- ...
- } else {
- EndConnection();
- return;
- }
- }
- graphDrawThread.start();
- ...
- // setTriggerMode()の処理など
- ...
- if (deviceConnection != null && endPointRead != null && isConnected) {
- for (int i = 0; i < MAX_REQUESTS; i++) {
- if (!queueRequest(requests[i], READ_BUFFER_SIZE)) {
- if (D) Log.e(TAG, "Request queueing error occured");
- EndConnection(); // thread stop
- return;
- }
- }
- }
- /* // 1つのループ内でUsbRequestの生成, initialize, queueするならこっち
- graphDrawThread.start();
- for (int i = 0; i < MAX_REQUESTS; i++) {
- final UsbRequest request = new UsbRequest();
- if (request.initialize(deviceConnection, endPointRead)) {
- if (!queueRequest(requests[i], READ_BUFFER_SIZE)) {
- if (D) Log.e(TAG, "Request queueing error occured");
- EndConnection(); // thread stop
- return;
- }
- } else {
- EndConnection();
- return;
- }
- }
- ...
- setTriggerMode()の処理など
- ...
- */
- // main loop
- for (; deviceConnection != null && endPointRead != null && isConnected ; ) {
- final UsbRequest request = deviceConnection.requestWait();
- if ((request != null) && (request.getEndpoint() == endPointRead)) {
- final ByteBuffer buf = (ByteBuffer)request.getClientData();
- if (buf != null) { // これはなくてもいいけど万が一
- buf.flip();
- offer(buf);
- queueRequest(request, READ_BUFFER_SIZE);
- }
- }
- }
- } // end of UsbReceiveThread#run
- private class GraphDrawThread extends Thread {
- int[] lawSamples;
- double[] g_wave;
- private volatile boolean running; // これはvolatileにしないとだめ
- GraphDrawThread() {
- g_wave = new double[DEFAULT_SAMPLE_LENGTH]; // normalizing samples (0~1)
- lawSamples = new int[DEFAULT_SAMPLE_LENGTH]; // law value samples
- waveMeta = new WaveAnalizer(); // waveMeta analysis
- running = true; // こっちに入れたほうがいいと思う
- }
- @Override
- public void run() {
- for (; running ;) {
- ByteBuffer buffer = null;
- try {
- // ここの待ち時間は好きなように。とりあえず30ミリ秒
- // 想定受信間隔以上にしておけばいいと思う。
- // 無限待ちにした場合は終了させる時にスレッドをinterruptしなきゃだめ
- buffer = mFramePool.poll(30, TimeUnit.MILLISECONDS);
- } catch (final InterruptedException e) {
- break;
- }
- if (buffer != null) {
- // bufferはキューに入れる前にflipしてlimitoが適切に設定されているのでclearしない
- for (int i = 0; i < sampleLength; i++) {
- lawSamples[i] = (int) buffer.getShort(); // 2byte to short
- }
- recycle(buf); // ここでプールに返却
- synchronized(g_wave) {
- // Convert to data with graph height set to 0~1
- for (int i = 0; i < sampleLength; i++) {
- g_wave[i] = (double) (lawSamples[i] - graph_min) / graph_fullscale; // 範囲を狭める
- }
- }
- waveMeta.analysisWave(g_wave); // waveMeta analysis
- mHandler.post(mSetWaveTask);
- } else {
- // #pollの待ち時間を想定受信間隔ぐらいにしていて、ここに来たときは
- // たぶんどこかの処理が間に合っていない
- }
- }
- } // end of GraphDrawThread#run
- // UIスレッドでの処理
- // 元々動的にmHander投げる時に生成していたのと内容は同じ
- // 全部UIスレッド上で処理する必要があるかどうかはみてない
- private final Runnable mSetWaveTask = new Runnable() {
- @Override
- public void run() {
- if (calibration == true) {
- calibrate(lawSamples);
- }
- if (biasCalibState > 0) {
- biasCalib(lawSamples);
- }
- if (autoSetState > 0) {
- autoSet();
- }
- synchronized(g_wave) {
- mGraph.setWave(g_wave, sampleLength); // draw graph
- }
- if (triggerMode == TGMODE_SINGLE) { // SINGLE mode
- // On the device side, since it will change freely internally, there is no need to send runninng mode change
- runModeSetStop();
- tbtn_stop.setChecked(true);
- if (D) Log.d(TAG, "Stop botton set cheched");
- }
- }
- };
- public void endThread() {
- running = false;
- }
- } // end of GraphDrawThread
- ...
- } // end of UsbReceiveThread
- ...
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement