Advertisement
Guest User

Untitled

a guest
Apr 28th, 2017
76
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.35 KB | None | 0 0
  1. // 最大フレームサイズ
  2. private static final int READ_BUFFER_SIZE = 1600;
  3. // 最大キューサイズ
  4. private static final int MAX_QUEUE_SIZE = 4;
  5. // プールの初期サイズ
  6. private static final int INIT_POOL_SZ = 4:
  7. // 最大プールサイズ
  8. private static final int MAX_POOL_SZ = 8;
  9. // 最大リクエストサイズ
  10. private static final int MAX_REQUESTS = 4;
  11.  
  12. // フレームデータプールを作る(リアローケーション防止のため)
  13. private final List<ByteBuffer> mPool = new ArrayList<ByteBuffer>(POOL_SZ);
  14. // FIFOのフレームデータキューを作る(なんでもいいけど普通はLinkedBlockingQueueを使う)
  15. private final LinkedBlockingQueue<ByteBuffer> mFrameQueue
  16. = new LinkedBlockingQueue<ByteBuffer>(MAX_QUEUE_SIZE);
  17.  
  18. // プールの初期化
  19. private void initPool() {
  20. for(int i = 0; i < POOL_SZ; i++) {
  21. mPool.add(ByteBuffer.allocateDirect(READ_BUFFER_SIZE)
  22. .order(ByteOrder.nativeOrder()));
  23. }
  24. }
  25.  
  26. private ByteBuffer obtain(final int sz) {
  27. ByteBuffer result = null;
  28. synchronized (mPool) {
  29. if (!mPool.isEmpty()) {
  30. result = mPool.remove(mPool.szie() - 1);
  31. }
  32. }
  33. if ((result == null) || (result.capacity() < sz)) {
  34. if (D) Log.w(TAG, "create ByteBuffer");
  35. result = ByteBuffer.allocateDirect(READ_BUFFER_SIZE)
  36. .order(ByteOrder.nativeOrder());
  37. }
  38. result.clear();
  39. return result;
  40. }
  41.  
  42. private void recycle(@NonNull final ByteBuffer buf) {
  43. synchronized (mPool) {
  44. if (mPool.size() < MAX_POOL_SZ) {
  45. mPool.add(buf);
  46. }
  47. }
  48. }
  49.  
  50. private void offer(@NonNull final ByteBuffer buffer) {
  51. if (!mFrameQueue.offer(buffer)) {
  52. if (D) Log.w(TAG, "frame queue is full, frame dropped");
  53. // 必要であれば、一番古いデータ=先頭を除去してから
  54. // 再度offerを試みるとよい
  55. }
  56. }
  57. ...
  58. private boolean queueRequest(@NonNull final UsbRequest request,
  59. final int read_sz) {
  60.  
  61. boolean result = false;
  62. final ByteBuffer buf = obtain(read_sz);
  63. if (buf != null) {
  64. request.setClientData(buf);
  65. result = request.queue(buf, read_sz)) {
  66. }
  67. return result;
  68. }
  69.  
  70. private class UsbReceiveThread extends Thread {
  71. private GraphDrawThread graphDrawThread;
  72.  
  73. UsbReceiveThread() {
  74. super("UsbReceiveThread");
  75. initPool();
  76. graphDrawThread = new GraphDrawThread();
  77. }
  78.  
  79. @Override
  80. public void run() {
  81. // この配列は必ずしもなくてもいい
  82. // その場合は先にgraphDrawThreadを起床しておいて
  83. // UsbRequestの生成, initialize, queueを1つのループ内で行う
  84. final UsbRequest requests[MAX_REQUESTS]
  85. = new UsbRequest[MAX_REQUESTS];
  86. for (int i = 0; i < MAX_REQUESTS; i++) {
  87. requests[i] = new UsbRequest();
  88. if (requests[i].initialize(deviceConnection, endPointRead)) {
  89. ...
  90. } else {
  91. EndConnection();
  92. return;
  93. }
  94. }
  95. graphDrawThread.start();
  96.  
  97. ...
  98. // setTriggerMode()の処理など
  99. ...
  100.  
  101. if (deviceConnection != null && endPointRead != null && isConnected) {
  102. for (int i = 0; i < MAX_REQUESTS; i++) {
  103. if (!queueRequest(requests[i], READ_BUFFER_SIZE)) {
  104. if (D) Log.e(TAG, "Request queueing error occured");
  105. EndConnection(); // thread stop
  106. return;
  107. }
  108. }
  109. }
  110.  
  111. /* // 1つのループ内でUsbRequestの生成, initialize, queueするならこっち
  112. graphDrawThread.start();
  113. for (int i = 0; i < MAX_REQUESTS; i++) {
  114. final UsbRequest request = new UsbRequest();
  115. if (request.initialize(deviceConnection, endPointRead)) {
  116. if (!queueRequest(requests[i], READ_BUFFER_SIZE)) {
  117. if (D) Log.e(TAG, "Request queueing error occured");
  118. EndConnection(); // thread stop
  119. return;
  120. }
  121. } else {
  122. EndConnection();
  123. return;
  124. }
  125. }
  126. ...
  127. setTriggerMode()の処理など
  128. ...
  129. */
  130.  
  131. // main loop
  132. for (; deviceConnection != null && endPointRead != null && isConnected ; ) {
  133. final UsbRequest request = deviceConnection.requestWait();
  134. if ((request != null) && (request.getEndpoint() == endPointRead)) {
  135. final ByteBuffer buf = (ByteBuffer)request.getClientData();
  136. if (buf != null) { // これはなくてもいいけど万が一
  137. buf.flip();
  138. offer(buf);
  139. queueRequest(request, READ_BUFFER_SIZE);
  140. }
  141. }
  142. }
  143. } // end of UsbReceiveThread#run
  144.  
  145. private class GraphDrawThread extends Thread {
  146. int[] lawSamples;
  147. double[] g_wave;
  148. private volatile boolean running; // これはvolatileにしないとだめ
  149.  
  150. GraphDrawThread() {
  151. g_wave = new double[DEFAULT_SAMPLE_LENGTH]; // normalizing samples (0~1)
  152. lawSamples = new int[DEFAULT_SAMPLE_LENGTH]; // law value samples
  153. waveMeta = new WaveAnalizer(); // waveMeta analysis
  154. running = true; // こっちに入れたほうがいいと思う
  155. }
  156.  
  157. @Override
  158. public void run() {
  159. for (; running ;) {
  160. ByteBuffer buffer = null;
  161. try {
  162. // ここの待ち時間は好きなように。とりあえず30ミリ秒
  163. // 想定受信間隔以上にしておけばいいと思う。
  164. // 無限待ちにした場合は終了させる時にスレッドをinterruptしなきゃだめ
  165. buffer = mFramePool.poll(30, TimeUnit.MILLISECONDS);
  166. } catch (final InterruptedException e) {
  167. break;
  168. }
  169. if (buffer != null) {
  170. // bufferはキューに入れる前にflipしてlimitoが適切に設定されているのでclearしない
  171. for (int i = 0; i < sampleLength; i++) {
  172. lawSamples[i] = (int) buffer.getShort(); // 2byte to short
  173. }
  174. recycle(buf); // ここでプールに返却
  175.  
  176. synchronized(g_wave) {
  177. // Convert to data with graph height set to 0~1
  178. for (int i = 0; i < sampleLength; i++) {
  179. g_wave[i] = (double) (lawSamples[i] - graph_min) / graph_fullscale; // 範囲を狭める
  180. }
  181. }
  182. waveMeta.analysisWave(g_wave); // waveMeta analysis
  183. mHandler.post(mSetWaveTask);
  184. } else {
  185. // #pollの待ち時間を想定受信間隔ぐらいにしていて、ここに来たときは
  186. // たぶんどこかの処理が間に合っていない
  187. }
  188. }
  189. } // end of GraphDrawThread#run
  190.  
  191. // UIスレッドでの処理
  192. // 元々動的にmHander投げる時に生成していたのと内容は同じ
  193. // 全部UIスレッド上で処理する必要があるかどうかはみてない
  194. private final Runnable mSetWaveTask = new Runnable() {
  195. @Override
  196. public void run() {
  197. if (calibration == true) {
  198. calibrate(lawSamples);
  199. }
  200.  
  201. if (biasCalibState > 0) {
  202. biasCalib(lawSamples);
  203. }
  204.  
  205. if (autoSetState > 0) {
  206. autoSet();
  207. }
  208.  
  209. synchronized(g_wave) {
  210. mGraph.setWave(g_wave, sampleLength); // draw graph
  211. }
  212.  
  213. if (triggerMode == TGMODE_SINGLE) { // SINGLE mode
  214.  
  215. // On the device side, since it will change freely internally, there is no need to send runninng mode change
  216. runModeSetStop();
  217.  
  218. tbtn_stop.setChecked(true);
  219. if (D) Log.d(TAG, "Stop botton set cheched");
  220. }
  221. }
  222. };
  223.  
  224. public void endThread() {
  225. running = false;
  226. }
  227. } // end of GraphDrawThread
  228.  
  229. ...
  230.  
  231. } // end of UsbReceiveThread
  232.  
  233. ...
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement