Check-in [7dadf72775]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment: user: pine tags: trunk EDITED soft/JK20/jni/rda/RDA.c EDITED soft/JK20/src/JK20.java ADDED soft/JK20/src/res/img/logo.png EDITED soft/JK20/src/view/StationListView.java EDITED soft/JK20/src/view/View.java EDITED soft/firmware/src/u2s.c
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:7dadf727750999f4dd7d1e37af80a40dbd911cb2
User & Date: pine 2016-05-15 13:02:29
Context
2016-05-21
03:29
user: pine tags: trunk EDITED soft/JK20/jni/rda/RDA.c EDITED soft/JK20/jni/rda/RDA.java EDITED soft/JK20/src/JK20.java EDITED soft/JK20/src/view/StationListView.java EDITED soft/firmware/lib/sys/uart.c EDITED soft/firmware/src/main.c DELETED soft/firmware/src/main_.c EDITED soft/firmware/src/u2s.c check-in: 20cda04cde user: pine tags: trunk
2016-05-15
13:02
user: pine tags: trunk EDITED soft/JK20/jni/rda/RDA.c EDITED soft/JK20/src/JK20.java ADDED soft/JK20/src/res/img/logo.png EDITED soft/JK20/src/view/StationListView.java EDITED soft/JK20/src/view/View.java EDITED soft/firmware/src/u2s.c check-in: 7dadf72775 user: pine tags: trunk
2016-05-14
00:59
user: pine tags: trunk EDITED .fossil-settings/binary-glob EDITED .fossil-settings/ignore-glob EDITED soft/JK20/build.xml ADDED soft/JK20/jni/Makefile ADDED soft/JK20/jni/foreach.sh ADDED soft/JK20/jni/rda/Makefile ADDED soft/JK20/jni/rda/RDA.c ADDED soft/JK20/jni/rda/RDA.java EDITED soft/JK20/src/Config.java ADDED soft/JK20/src/ConfigSaver.java ADDED soft/JK20/src/ControlMessage.java EDITED soft/JK20/src/JK20.java ADDED soft/JK20/src/Version.java ADDED soft/JK20/src/res/img/gbulboff.png ADDED soft/JK20/src/res/img/gbulbon.png ADDED soft/JK20/src/res/img/rbulboff.png ADDED soft/JK20/src/res/img/rbulbon.png ADDED soft/JK20/src/view/LevelView.java ADDED soft/JK20/src/view/StationListView.java ADDED soft/JK20/src/view/View.java EDITED soft/firmware/Makefile DELETED soft/firmware/lib/sys/stimer.d DELETED soft/firmware/lib/sys/uart.d DELETED soft/firmware/src/fusb/fusb.d DELETED soft/firmware/src/fusb/fusb_proto.d DELETED soft/firmware/src/fusb/fusb_reg.d DELETED soft/firmware/src/led.d DELETED soft/firmware/src/main.d DELETED soft/firmware/src/u2s.d EDITED soft/firmware/src/u2s_shared.h DELETED soft/firmware/src/util.d DELETED soft/libk20/Makefile DELETED soft/libk20/k20tool.c check-in: 8d3a66aa88 user: pine tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to soft/JK20/jni/rda/RDA.c.

68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
...
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
...
378
379
380
381
382
383
384

385
386
387
388
389
390
391
...
412
413
414
415
416
417
418

419
420
421
/*
 * Class:     org_jk20_jni_rda_RDA
 * Method:    open
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_org_jk20_jni_rda_RDA_open(JNIEnv *env, jobject thisObject)
{
    int i, cnt, ndev;
    libusb_device **devs;
    libusb_device *dev;
    int r;
    struct libusb_device_descriptor desc;

    cnt = libusb_get_device_list(context, &devs);
    if (cnt < 0)
    {
        _throwException(env, USB_EXCEPTION, "can not get divice list");
        goto error;
    }

    dev  = NULL;
    ndev = 0;
    for (i = 0; i < cnt; i++)
    {
        r = libusb_get_device_descriptor(devs[i], &desc);
        if (r < 0) {
            _throwException(env, USB_EXCEPTION, "failed to get device descriptor");
            goto error;
        }
................................................................................
        {
            printf("%04x:%04x (bus %d, device %d)\n",
                    desc.idVendor, desc.idProduct,
                    libusb_get_bus_number(devs[i]), libusb_get_device_address(devs[i]));
            fflush(stdout);
            dev = devs[i];
            /* XXX only first found device */
            if (ndev == 0)
                break;
            ndev++;
        }
    }

    if (dev == NULL)
    {
        _throwException(env, USB_EXCEPTION, "can not find device");
        goto error;
................................................................................
        for (i = 0; i < n; i++)
        {
            if ((i % 16 == 0))
                printf("\r\n     ");
            printf("%02hhX ", buf[i]);
        }
        printf("\r\n");

    }
#endif
    return n;
}

/*
 *
................................................................................
        {
            if ((i % 16 == 0))
                printf("\r\n     ");
            printf("%02hhX ", buf[i]);
        }
        printf("\r\n");
    }

#endif
    return n;
}







|













<







 







<
|
<







 







>







 







>



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

89
90
91
92
93
94
95
..
99
100
101
102
103
104
105

106

107
108
109
110
111
112
113
...
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
...
410
411
412
413
414
415
416
417
418
419
420
/*
 * Class:     org_jk20_jni_rda_RDA
 * Method:    open
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_org_jk20_jni_rda_RDA_open(JNIEnv *env, jobject thisObject)
{
    int i, cnt;
    libusb_device **devs;
    libusb_device *dev;
    int r;
    struct libusb_device_descriptor desc;

    cnt = libusb_get_device_list(context, &devs);
    if (cnt < 0)
    {
        _throwException(env, USB_EXCEPTION, "can not get divice list");
        goto error;
    }

    dev  = NULL;

    for (i = 0; i < cnt; i++)
    {
        r = libusb_get_device_descriptor(devs[i], &desc);
        if (r < 0) {
            _throwException(env, USB_EXCEPTION, "failed to get device descriptor");
            goto error;
        }
................................................................................
        {
            printf("%04x:%04x (bus %d, device %d)\n",
                    desc.idVendor, desc.idProduct,
                    libusb_get_bus_number(devs[i]), libusb_get_device_address(devs[i]));
            fflush(stdout);
            dev = devs[i];
            /* XXX only first found device */

            break;

        }
    }

    if (dev == NULL)
    {
        _throwException(env, USB_EXCEPTION, "can not find device");
        goto error;
................................................................................
        for (i = 0; i < n; i++)
        {
            if ((i % 16 == 0))
                printf("\r\n     ");
            printf("%02hhX ", buf[i]);
        }
        printf("\r\n");
        fflush(stdout);
    }
#endif
    return n;
}

/*
 *
................................................................................
        {
            if ((i % 16 == 0))
                printf("\r\n     ");
            printf("%02hhX ", buf[i]);
        }
        printf("\r\n");
    }
    fflush(stdout);
#endif
    return n;
}

Changes to soft/JK20/src/JK20.java.

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

61
62









63
64
65
66
67
68
69
70
71
72
73
74
75
76
77







78
79
80
81
82
83
84
..
85
86
87
88
89
90
91



92
93
94
95
96
97
98
...
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
...
154
155
156
157
158
159
160






161
162
163
164
165
166
167
168
169
        jk20Thread = Thread.currentThread();

        messageQueue = new ArrayBlockingQueue<ControlMessage>(MESSAGE_QUEUE_CAPACITY);

        config = new Config().load();
        configSaver = new ConfigSaver(config).start();
        SwingUtilities.invokeLater(() -> {
            view = new View();
        });

        rda = new RDA();
        try {
            rda.init();
//            rda.setChannel(88.5);
        } catch (Exception e) {
            System.out.println("RDA init error: " + e);
            terminate();
            return;
        }

//        boolean stereo = true;
        while (!needTerminate()) {
//            stereo = !stereo;
//

//            if (view != null)
//                view.setStereo(stereo);










            /* try to open device */
            try {
                rda.open();
            } catch (Exception e) {
                System.out.println("RDA open error: " + e);
                try {
                    final int RECONNECT_TIME = 2000;
                    Thread.sleep(RECONNECT_TIME);
                    continue;
                } catch (InterruptedException e2) {
                    System.out.println(getClass().getSimpleName() + " interrupted, " + e2);
                    terminate = true;
                    break;
                }







            }

            messageQueue.clear();
            while (!needTerminate()) {
                ControlMessage message;
                try {
                    message = messageQueue.take();
................................................................................
                } catch (InterruptedException e) {
                    System.out.println(getClass().getSimpleName() + " interrupted, " + e);
                    terminate = true;
                    break;
                }
                processMessage(message);
            }



        }
        terminate();
    }
    /**
     *
     */
    private boolean needTerminate() {
................................................................................
    }
    /**
     * Put message to queue of control thread
     */
    public void putMessage(ControlMessage message) {
        if (!messageQueue.offer(message)) {
            System.out.println("(W) " + getClass().getName() + ", queue overflow");
            try {
                messageQueue.put(message);
            } catch (InterruptedException e) {};
        }
    }
    /**
     *
     */
    public void terminate() {
        System.out.println(getClass().getName() + " terminate");
................................................................................
        if (rda != null) {
            rda.close();
            rda.destroy();
        }
        configSaver.terminate();
        System.exit(0);
    }






    /**
     *
     */
    public static JK20 getInstance() {
        return jk20;
    }

}








|












|

|
<
>
|
|
>
>
>
>
>
>
>
>
>






<
<
<
|
<
<
<
<
|
>
>
>
>
>
>
>







 







>
>
>







 







|
|
|







 







>
>
>
>
>
>






|
|
<
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77



78




79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
..
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
...
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
...
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186

        jk20Thread = Thread.currentThread();

        messageQueue = new ArrayBlockingQueue<ControlMessage>(MESSAGE_QUEUE_CAPACITY);

        config = new Config().load();
        configSaver = new ConfigSaver(config).start();
        SwingUtilities.invokeLater(() -> {
            view = new View().make();
        });

        rda = new RDA();
        try {
            rda.init();
//            rda.setChannel(88.5);
        } catch (Exception e) {
            System.out.println("RDA init error: " + e);
            terminate();
            return;
        }

        boolean first = true;
        while (!needTerminate()) {
            if (first) {

                first = false;
            } else {
                rda.close();
                try {
                    final int RECONNECT_TIME = 2000;
                    Thread.sleep(RECONNECT_TIME);
                } catch (InterruptedException e2) {
                    System.out.println(getClass().getSimpleName() + " interrupted, " + e2);
                    terminate = true;
                    break;
                }
            }

            /* try to open device */
            try {
                rda.open();
            } catch (Exception e) {
                System.out.println("RDA open error: " + e);



                continue;




            }

            /* apply current settings */
            try {
                rda.apply();
            } catch (Exception e) {
                System.out.println("RDA apply error: " + e);
                continue;
            }

            messageQueue.clear();
            while (!needTerminate()) {
                ControlMessage message;
                try {
                    message = messageQueue.take();
................................................................................
                } catch (InterruptedException e) {
                    System.out.println(getClass().getSimpleName() + " interrupted, " + e);
                    terminate = true;
                    break;
                }
                processMessage(message);
            }

            /* show "---.- MHz" if connection to device was lost */
            view.setFrequencyIndicator(0);
        }
        terminate();
    }
    /**
     *
     */
    private boolean needTerminate() {
................................................................................
    }
    /**
     * Put message to queue of control thread
     */
    public void putMessage(ControlMessage message) {
        if (!messageQueue.offer(message)) {
            System.out.println("(W) " + getClass().getName() + ", queue overflow");
//            try {
//                messageQueue.put(message);
//            } catch (InterruptedException e) {};
        }
    }
    /**
     *
     */
    public void terminate() {
        System.out.println(getClass().getName() + " terminate");
................................................................................
        if (rda != null) {
            rda.close();
            rda.destroy();
        }
        configSaver.terminate();
        System.exit(0);
    }
//    /**
//     *
//     */
//    private boolean sleep() {
//
//    }
    /**
     *
     */
    public static JK20 getInstance() {
        return jk20;
    }
}


Added soft/JK20/src/res/img/logo.png.

cannot compute difference between binary files

Changes to soft/JK20/src/view/StationListView.java.

35
36
37
38
39
40
41

42
43
44
45
46
47
48

        table.setShowVerticalLines(false);
        table.setShowHorizontalLines(false);
        table.setTableHeader(null);
        table.setDefaultRenderer(Object.class, new StationListTableCellRenderer());
        table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        table.setColumnSelectionAllowed(false);


        synchronized (config) {
            /* TODO set FONT from config */
            font = config.listFont;
            table.setFont(font);
            table.setBackground(config.bgColor);
            table.setForeground(config.fgColor);







>







35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

        table.setShowVerticalLines(false);
        table.setShowHorizontalLines(false);
        table.setTableHeader(null);
        table.setDefaultRenderer(Object.class, new StationListTableCellRenderer());
        table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        table.setColumnSelectionAllowed(false);
        table.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));

        synchronized (config) {
            /* TODO set FONT from config */
            font = config.listFont;
            table.setFont(font);
            table.setBackground(config.bgColor);
            table.setForeground(config.fgColor);

Changes to soft/JK20/src/view/View.java.

31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
..
94
95
96
97
98
99
100



101
102
103
104

105



106

107
108
109
110
111
112
113
114
115
116
117
118
119
120


121
122
123
124
125
126
127
128

129
130
131
132
133
134
135
136
137
138
139
140
141
142
...
150
151
152
153
154
155
156
157

158
159
160
161
162
163
164
165
166
167
168
169
170


171
172
173
174
175
176
177
...
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198

199
200
201
202
203
204
205
...
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
    private JPanel listPanel;
    private JScrollPane listScrollPane;
    private StationListView stationListView;
    private LevelView rssiLevel;
    private ImageIcon[] redBulb;
    private ImageIcon[] greenBulb;

    private JLabel frequencyIndicator;
    private JLabel stereoIndicator;
    private JLabel seekIndicator;
    private JLabel stationIndicator;
    
    /**
     *
     */
    public View() {
        Config config = JK20.getInstance().config;

        setName("JK20 " + Version.getString());
        setUndecorated(true);

        Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
        Dimension winSize;
................................................................................
//            sidePanel.setPreferredSize(new Dimension(sideWidth, 0));

//            rssiLevel = new LevelView();
//            rssiLevel.setMinimumSize(new Dimension(sideWidth, 12));
//            rssiLevel.setMaximumSize(new Dimension(sideWidth, 64));
//            rssiLevel.setPreferredSize(new Dimension(sideWidth, 24));




            JPanel freqFrame = new JPanel();
            freqFrame.setBorder(BorderFactory.createLineBorder(Color.GRAY, PADDING));
            freqFrame.setAlignmentX(LEFT_ALIGNMENT);
//            freqFrame.setMinimumSize(new Dimension(sideWidth / 2, 12));

//            freqFrame.setPreferredSize(new Dimension(sideWidth, 24));



//            freqFrame.setMaximumSize(new Dimension(Short.MAX_VALUE, Short.MAX_VALUE));

            freqFrame.setOpaque(false);

            frequencyIndicator = new JLabel();
            freqFrame.add(frequencyIndicator);

            stereoIndicator   = new JLabel("Stereo" , JLabel.LEFT);
            stationIndicator  = new JLabel("Station", JLabel.LEFT);
            seekIndicator     = new JLabel("Seek"   , JLabel.LEFT);

            setStereoIndicator(false);
            setStationIndicator(false);
            setSeekIndicator(false, true);
            setFrequencyIndicator(0);



            sidePanel.add(freqFrame);
            sidePanel.add(Box.createVerticalStrut(PADDING));
            sidePanel.add(stationIndicator);
            sidePanel.add(Box.createVerticalStrut(PADDING));
            sidePanel.add(seekIndicator);
            sidePanel.add(Box.createVerticalStrut(PADDING));
            sidePanel.add(stereoIndicator);
            sidePanel.add(Box.createVerticalGlue());

//            sidePanel.add(rssiLevel);

            GridBagConstraints gridConstraint = new GridBagConstraints();
            gridConstraint.gridx   = 0;
            gridConstraint.gridy   = 0;
            gridConstraint.weightx = 1.0;
            gridConstraint.weighty = 1.0;
            gridConstraint.anchor  = GridBagConstraints.NORTH;
            gridConstraint.fill    = GridBagConstraints.BOTH;
            mainPanel.add(sidePanel, gridConstraint);
        }        

        /*
         * Station list panel.
................................................................................
//            final int listWidth = (int)(winSize.getWidth() * 2 / 3);
//            listPanel.setPreferredSize(new Dimension(listWidth, Short.MAX_VALUE));

            stationListView = new StationListView();
            listScrollPane = new JScrollPane(stationListView.getComponent());
            listScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
            listScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
            listScrollPane.setBorder(makePadding());

            listScrollPane.setOpaque(false);
            listScrollPane.getViewport().setOpaque(false);

            runLater(() -> {
                listScrollPane.revalidate();
                listScrollPane.repaint();
            });

            listPanel.add(listScrollPane);

            GridBagConstraints gridConstraint = new GridBagConstraints();
            gridConstraint.gridx   = 1;
            gridConstraint.gridy   = 0;


            gridConstraint.anchor  = GridBagConstraints.NORTHWEST;
            gridConstraint.fill    = GridBagConstraints.BOTH;
            mainPanel.add(listPanel, gridConstraint);
        }        
        /*
         * Set colors, fonts
         */
................................................................................
            mainPanel.setBackground(config.bgColor);
            stereoIndicator.setForeground(config.labelColor);
            stereoIndicator.setFont(config.labelFont);
            seekIndicator.setForeground(config.labelColor);
            seekIndicator.setFont(config.labelFont);
            stationIndicator.setForeground(config.labelColor);
            stationIndicator.setFont(config.labelFont);
            frequencyIndicator.setForeground(config.labelColor);
            frequencyIndicator.setFont(config.freqFont);
        }

        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                JK20.getInstance().doTerminate();
            }
        });
        
        setContentPane(mainPanel);        
        setVisible(true);

    }
    /**
     *
     */
    public void setStereoIndicator(boolean stereo) {
        runLater(() -> {
            Icon icon = greenBulb[stereo ? 1 : 0];
................................................................................
            String sval;

            if (value == 0)
                sval = "---.-- MHz";
            else
                sval = String.format(Locale.US, "%03.2f MHz", value);

            frequencyIndicator.setText(sval);
        });
    }

    /**
     *
     */
    private Border makePadding() {







|







|







 







>
>
>



|
>
|
>
>
>
|
>
|

<
|










>
>

|






>





|
|







 







|
>













>
>







 







|
|











>







 







|







31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
..
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116

117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
...
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
...
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
...
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
    private JPanel listPanel;
    private JScrollPane listScrollPane;
    private StationListView stationListView;
    private LevelView rssiLevel;
    private ImageIcon[] redBulb;
    private ImageIcon[] greenBulb;

    private JLabel freqIndicator;
    private JLabel stereoIndicator;
    private JLabel seekIndicator;
    private JLabel stationIndicator;
    
    /**
     *
     */
    public View make() {
        Config config = JK20.getInstance().config;

        setName("JK20 " + Version.getString());
        setUndecorated(true);

        Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
        Dimension winSize;
................................................................................
//            sidePanel.setPreferredSize(new Dimension(sideWidth, 0));

//            rssiLevel = new LevelView();
//            rssiLevel.setMinimumSize(new Dimension(sideWidth, 12));
//            rssiLevel.setMaximumSize(new Dimension(sideWidth, 64));
//            rssiLevel.setPreferredSize(new Dimension(sideWidth, 24));

            freqIndicator = new JLabel();
            freqIndicator.setBorder(makePadding());

            JPanel freqFrame = new JPanel();
            freqFrame.setBorder(BorderFactory.createLineBorder(Color.GRAY, PADDING));
            freqFrame.setAlignmentX(LEFT_ALIGNMENT);
            runLater(() -> {
                final int height = freqIndicator.getFont().getSize() * 2 + 8;
                freqFrame.setPreferredSize(new Dimension(freqFrame.getWidth(), height));
                freqFrame.setMaximumSize  (new Dimension(freqFrame.getWidth() * 2, height));
                freqFrame.setMinimumSize  (new Dimension(freqFrame.getWidth(), height));
            });
//            freqFrame.setBackground(Color.BLUE);
            freqFrame.setBackground(new Color(0x25, 0x20, 0x05));
            freqFrame.setOpaque(true);


            freqFrame.add(freqIndicator);

            stereoIndicator   = new JLabel("Stereo" , JLabel.LEFT);
            stationIndicator  = new JLabel("Station", JLabel.LEFT);
            seekIndicator     = new JLabel("Seek"   , JLabel.LEFT);

            setStereoIndicator(false);
            setStationIndicator(false);
            setSeekIndicator(false, true);
            setFrequencyIndicator(0);

            JLabel logo = new JLabel(new ImageIcon(getClass().getResource("/res/img/logo.png")));

            sidePanel.add(freqFrame);
            sidePanel.add(Box.createVerticalStrut(PADDING * 2));
            sidePanel.add(stationIndicator);
            sidePanel.add(Box.createVerticalStrut(PADDING));
            sidePanel.add(seekIndicator);
            sidePanel.add(Box.createVerticalStrut(PADDING));
            sidePanel.add(stereoIndicator);
            sidePanel.add(Box.createVerticalGlue());
            sidePanel.add(logo);
//            sidePanel.add(rssiLevel);

            GridBagConstraints gridConstraint = new GridBagConstraints();
            gridConstraint.gridx   = 0;
            gridConstraint.gridy   = 0;
            gridConstraint.weightx = 0.5;
            gridConstraint.weighty = 0.5;
            gridConstraint.anchor  = GridBagConstraints.NORTH;
            gridConstraint.fill    = GridBagConstraints.BOTH;
            mainPanel.add(sidePanel, gridConstraint);
        }        

        /*
         * Station list panel.
................................................................................
//            final int listWidth = (int)(winSize.getWidth() * 2 / 3);
//            listPanel.setPreferredSize(new Dimension(listWidth, Short.MAX_VALUE));

            stationListView = new StationListView();
            listScrollPane = new JScrollPane(stationListView.getComponent());
            listScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
            listScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
//            listScrollPane.setBorder(makePadding());
            listScrollPane.setBorder(BorderFactory.createLineBorder(Color.GRAY, PADDING));
            listScrollPane.setOpaque(false);
            listScrollPane.getViewport().setOpaque(false);

            runLater(() -> {
                listScrollPane.revalidate();
                listScrollPane.repaint();
            });

            listPanel.add(listScrollPane);

            GridBagConstraints gridConstraint = new GridBagConstraints();
            gridConstraint.gridx   = 1;
            gridConstraint.gridy   = 0;
            gridConstraint.weightx = 0.5;
            gridConstraint.weighty = 0.5;
            gridConstraint.anchor  = GridBagConstraints.NORTHWEST;
            gridConstraint.fill    = GridBagConstraints.BOTH;
            mainPanel.add(listPanel, gridConstraint);
        }        
        /*
         * Set colors, fonts
         */
................................................................................
            mainPanel.setBackground(config.bgColor);
            stereoIndicator.setForeground(config.labelColor);
            stereoIndicator.setFont(config.labelFont);
            seekIndicator.setForeground(config.labelColor);
            seekIndicator.setFont(config.labelFont);
            stationIndicator.setForeground(config.labelColor);
            stationIndicator.setFont(config.labelFont);
            freqIndicator.setForeground(config.labelColor);
            freqIndicator.setFont(config.freqFont);
        }

        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                JK20.getInstance().doTerminate();
            }
        });
        
        setContentPane(mainPanel);        
        setVisible(true);
        return this;
    }
    /**
     *
     */
    public void setStereoIndicator(boolean stereo) {
        runLater(() -> {
            Icon icon = greenBulb[stereo ? 1 : 0];
................................................................................
            String sval;

            if (value == 0)
                sval = "---.-- MHz";
            else
                sval = String.format(Locale.US, "%03.2f MHz", value);

            freqIndicator.setText(sval);
        });
    }

    /**
     *
     */
    private Border makePadding() {

Changes to soft/firmware/src/u2s.c.

1
2


3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
..
39
40
41
42
43
44
45




46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
..
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
...
118
119
120
121
122
123
124
125
126
127

























































































































128
129
130
131
132




133
134
135
136
137
138

139



































140



141
142
143
144
145
146
147
148
149


150
151

152
































153
154
155
156
157



158
159
#include <xc.h>
#include <debug.h>


#include "util.h"
#include "u2s.h"
#include "fusb/fusb.h"
#include "fusb/fusb_reg.h"
#include "led.h"
#include "u2s_shared.h"

//#define DEBUGU2S

#ifdef DEBUGU2S
    #define DEBUGU2S_STR(s)    debug_str(s)
    #define DEBUGU2S_CHAR(c)   debug_char(c)
    #define DEBUGU2S_HEX(h, l) debug_hex(h, l)
#else
    #define DEBUGU2S_STR(s)
    #define DEBUGU2S_CHAR(c)
    #define DEBUGU2S_HEX(h, l)
#endif

#define U2S_BUF_SIZE    EP1_BUFSIZE
static uint8 u2s_buf[U2S_BUF_SIZE];

static void u2s_error(uint8 error);

................................................................................
void u2s_init()
{
    ANSEL  = 0;
    ANSELH = 0;

    /* setup i2c */
    {






    }
//    IO0_TRIS  = 1;
//    IO1_TRIS  = 1;
//    IO2_TRIS  = 1;
//    IO3_TRIS  = 1;
//    KEY_TRIS  = 0;
//    MOSI_TRIS = 1;
//    MISO_TRIS = 1;
//    SCK_TRIS  = 1;
}

/*
 * receive data from host
 */
void u2s_receive(uint8 *buf, uint8 len)
{
    struct u2s_req_t *req;
    struct u2s_resp_t *resp;
    uint8 olen;

    led_blink(2);

#ifdef DEBUGU2S
    DEBUGU2S_STR("u2s receive:");
    util_printarray(buf, len);
#endif

    req = (struct u2s_req_t *)buf;
    resp = (struct u2s_resp_t *)u2s_buf;

    resp->cmd = req->cmd;
................................................................................
    {
        case U2S_CMD_RDA_WRITE:
            if (len != (U2S_REQ_HEAD_SIZE + sizeof(union rda_write_data_t)))
            {
                u2s_error(U2S_ERROR_CMDLENMISMATCH);
                return;
            }
            if (_rda_write(req->rda_write.data) != 0)
            {
                u2s_error(U2S_ERROR_I2C_NACK);
                return;
            }
            break;
        case U2S_CMD_RDA_READ:
            if (len != U2S_REQ_HEAD_SIZE)
            {
                u2s_error(U2S_ERROR_CMDLENMISMATCH);
                return;
            }
            if (_rda_read(resp->rda_read.data) != 0)
            {
                u2s_error(U2S_ERROR_I2C_NACK);
                return;
            }
            olen += sizeof(union rda_write_data_t);
            break;
        default:
................................................................................
 */
static void u2s_error(uint8 error)
{
    u2s_buf[0] = U2S_CMD_ERROR;
    u2s_buf[1] = error;
    u2s_send(u2s_buf, 2);
}

/*
 *

























































































































 * RETURN
 *     0 on success, nonzero on error
 */
static uint8 _rda_write(uint8* data)
{




#ifdef DEBUGU2S
    DEBUGU2S_STR("rda write:");
    util_printarray(data, sizeof(union rda_write_data_t));
#endif

    /* TODO */





































    return 0;



}

/*
 *
 * RETURN
 *     0 on success, nonzero on error
 */
static uint8 _rda_read(uint8* data)
{



    /* TODO */


































#ifdef DEBUGU2S
    DEBUGU2S_STR("rda write:");
    util_printarray(data, sizeof(union rda_read_data_t));
#endif
    return 0;



}



>
>







|

|
|
|
|

|
|
|







 







>
>
>
>
|
<
<
<
<
<
<
<
<
<
<













|
|







 







|











|







 










>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





>
>
>
>
|
<



<
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>









>
>

<
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|



>
>
>


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
..
41
42
43
44
45
46
47
48
49
50
51
52










53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
..
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
...
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254

255
256
257

258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310

311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
#include <xc.h>
#include <debug.h>
#include <sys.h>
#include <stimer.h>
#include "util.h"
#include "u2s.h"
#include "fusb/fusb.h"
#include "fusb/fusb_reg.h"
#include "led.h"
#include "u2s_shared.h"

#define DEBUG_THIS

#ifdef DEBUG_THIS
    #define DEBUG_THIS_STR(s)    debug_str(s)
    #define DEBUG_THIS_CHAR(c)   debug_char(c)
    #define DEBUG_THIS_HEX(h, l) debug_hex(h, l)
#else
    #define DEBUG_THIS_STR(s)
    #define DEBUG_THIS_CHAR(c)
    #define DEBUG_THIS_HEX(h, l)
#endif

#define U2S_BUF_SIZE    EP1_BUFSIZE
static uint8 u2s_buf[U2S_BUF_SIZE];

static void u2s_error(uint8 error);

................................................................................
void u2s_init()
{
    ANSEL  = 0;
    ANSELH = 0;

    /* setup i2c */
    {
#define I2C_CLK    (100 * 1000) /* Hz */
        SSPADD = CCLK / 4 / I2C_CLK - 1;
        SSPCON1bits.SSPM  = 8;  /* 0b1000 master mode */
        SSPCON1bits.SSPEN = 1; /* enable serial port */
    }










}

/*
 * receive data from host
 */
void u2s_receive(uint8 *buf, uint8 len)
{
    struct u2s_req_t *req;
    struct u2s_resp_t *resp;
    uint8 olen;

    led_blink(2);

#ifdef DEBUG_THIS
    DEBUG_THIS_STR("u2s receive:");
    util_printarray(buf, len);
#endif

    req = (struct u2s_req_t *)buf;
    resp = (struct u2s_resp_t *)u2s_buf;

    resp->cmd = req->cmd;
................................................................................
    {
        case U2S_CMD_RDA_WRITE:
            if (len != (U2S_REQ_HEAD_SIZE + sizeof(union rda_write_data_t)))
            {
                u2s_error(U2S_ERROR_CMDLENMISMATCH);
                return;
            }
            if (_rda_write(req->rda_write.data8) != 0)
            {
                u2s_error(U2S_ERROR_I2C_NACK);
                return;
            }
            break;
        case U2S_CMD_RDA_READ:
            if (len != U2S_REQ_HEAD_SIZE)
            {
                u2s_error(U2S_ERROR_CMDLENMISMATCH);
                return;
            }
            if (_rda_read(resp->rda_read.data8) != 0)
            {
                u2s_error(U2S_ERROR_I2C_NACK);
                return;
            }
            olen += sizeof(union rda_write_data_t);
            break;
        default:
................................................................................
 */
static void u2s_error(uint8 error)
{
    u2s_buf[0] = U2S_CMD_ERROR;
    u2s_buf[1] = error;
    u2s_send(u2s_buf, 2);
}

/*
 *
 */
static void _i2c_reset() {
    SSPCON1bits.SSPEN = 0; /* disable serial port */
    SSPCON1bits.SSPEN = 1; /* enable serial port */
}

#define SSP_TIMEOUT  5 /* ms */

/*
 *
 */
static uint8 _i2c_start() {
    uint16 to;

    PIR1bits.SSPIF = 0;

    SSPCON2bits.SEN = 1;
    stimer_set(&to);
    while (!PIR1bits.SSPIF)
    {
        if (stimer_delta(to) >= SSP_TIMEOUT)
        {
            DEBUG_THIS_STR("(E) ST\n");
            return 0;
        }
    }
    PIR1bits.SSPIF = 0;
    return 1;
}
/*
 *
 */
static uint8 _i2c_stop() {
    uint16 to;

    SSPCON2bits.PEN = 1;
    stimer_set(&to);
    while (!PIR1bits.SSPIF)
    {
        if (stimer_delta(to) >= SSP_TIMEOUT)
        {
            DEBUG_THIS_STR("(E) PT");
            return 0;
        }
    }
    PIR1bits.SSPIF = 0;
    return 1;
}
/*
 *
 */
static uint8 _i2c_write(uint8 data) {
    uint16 to;

    SSPBUF = data;
    stimer_set(&to);
    while (!PIR1bits.SSPIF)
    {
        if (stimer_delta(to) >= SSP_TIMEOUT)
        {
            DEBUG_THIS_STR("(E) DWT\n");
            return 0;
        }
    }
    PIR1bits.SSPIF = 0;
    return 1;
}
/*
 *
 */
static uint8 _i2c_read(uint8 *data) {
    uint16 to;

    SSPCON2bits.RCEN = 1;

    stimer_set(&to);
    while (!PIR1bits.SSPIF)
    {
        if (stimer_delta(to) >= SSP_TIMEOUT)
        {
            DEBUG_THIS_STR("(E) DRT\n");
            return 0;
        }
    }
    *data = SSPBUF;
    PIR1bits.SSPIF = 0;
    return 1;
}
/*
 *
 */
static inline uint8 _i2c_getnack() {
    return SSPCON2bits.ACKSTAT;
}
/*
 *
 */
static uint8 _i2c_setnack(uint8 nack) {
    uint16 to;

    if (nack)
        SSPCON2bits.ACKDT = 1;
    else
        SSPCON2bits.ACKDT = 0;

    SSPCON2bits.ACKEN = 1;

    stimer_set(&to);
    while (SSPCON2bits.ACKEN)
    {
        if (stimer_delta(to) >= SSP_TIMEOUT)
        {
            DEBUG_THIS_STR("(E) SNT\n");
            return 0;
        }
    }
    return 1;
}

/*
 *
 * RETURN
 *     0 on success, nonzero on error
 */
static uint8 _rda_write(uint8* data)
{
    uint8 len;
    uint8 *pbuf;

    DEBUG_THIS_STR("rda write:");
#ifdef DEBUG_THIS

    util_printarray(data, sizeof(union rda_write_data_t));
#endif


#define RDA_ADDRESS    0x10

    /* START */
    if (!_i2c_start())
        goto error;

    /* Write address. */
    if (!_i2c_write((RDA_ADDRESS << 1) | 0))
        goto error;

    /* read ACK */
    if (_i2c_getnack())
    {
        DEBUG_THIS_STR("(E) ANACK\n");
        goto error;
    }

    /* Write data. */
    len = sizeof(union rda_write_data_t);
    pbuf = data;
    while (len--) {
        /* write data byte */
        if (!_i2c_write(*pbuf++))
            goto error;

        /* read ACK */
        if (_i2c_getnack())
        {
            DEBUG_THIS_STR("(E) DNACK\n");
            goto error;
        }
    }

    /* STOP. */
    if (!_i2c_stop())
        goto error;

    return 0;
error:
    _i2c_reset();
    return 1;
}

/*
 *
 * RETURN
 *     0 on success, nonzero on error
 */
static uint8 _rda_read(uint8* data)
{
    int len;
    uint8 *pbuf;


    DEBUG_THIS_STR("rda read\n");

    /* START */
    if (!_i2c_start())
        goto error;

    /* Write address. */
    if (!_i2c_write((RDA_ADDRESS << 1) | 1))
        goto error;

    /* read ACK */
    if (_i2c_getnack())
    {
        DEBUG_THIS_STR("(E) ANACK\n");
        goto error;
    }

    len = sizeof(union rda_read_data_t);
    pbuf = data;

    while (len--) {
        /* read data byte */
        if (!_i2c_read(pbuf++))
            goto error;

        /* write ACK */
        if (!_i2c_setnack(len ? 0 : 1))
            goto error;
    }

    /* STOP. */
    if (!_i2c_stop())
        goto error;

#ifdef DEBUG_THIS
    DEBUG_THIS_STR("rdata:");
    util_printarray(data, sizeof(union rda_read_data_t));
#endif
    return 0;
error:
    _i2c_reset();
    return 1;
}