Skip to content

Commit fe0eb2d

Browse files
authored
Second round of expanding test coverage (#144)
* Add HX717 tests * - Test for SN74cbt mux - Fix bug in mux implementation * Add test for 74hc4052 * add encoder test case * Add test case for ws281x * dwarf input test case * add fan test case
1 parent caeded5 commit fe0eb2d

16 files changed

+1171
-25
lines changed

hw/arm/prusa/parts/74CBTLV3257.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ static void cbtl3257_select(void *opaque, int n, int level){
8383
{
8484
if (s->levels[old_sel][i] != s->levels[s->select][i])
8585
{
86-
qemu_set_irq(s->irq[n],s->levels[s->select][i]);
86+
qemu_set_irq(s->irq[i],s->levels[s->select][i]);
8787
}
8888
}
8989
}
@@ -95,11 +95,11 @@ static void cbtl3257_nOE(void *opaque, int n, int level){
9595
{
9696
if (s->oe)
9797
{
98-
qemu_set_irq(s->irq[n],s->levels[s->select][i]);
98+
qemu_set_irq(s->irq[i],s->levels[s->select][i]);
9999
}
100100
else
101101
{
102-
qemu_irq_lower(s->irq[n]);
102+
qemu_irq_lower(s->irq[i]);
103103
}
104104
}
105105
}

hw/arm/prusa/parts/encoder_input.c

+7-8
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,7 @@ struct InputState {
4646
/*< private >*/
4747
/*< public >*/
4848
qemu_irq irq_enc_button;
49-
qemu_irq irq_enc_a;
50-
qemu_irq irq_enc_b;
49+
qemu_irq irq_enc[2];
5150
qemu_irq irq_rst;
5251
qemu_irq cursor_xy[2];
5352
qemu_irq tap;
@@ -114,8 +113,8 @@ static void encoder_input_timer_expire(void *opaque)
114113
s->phase+=3;
115114
}
116115
s->phase = s->phase%4;
117-
qemu_set_irq(s->irq_enc_a, (encoder_input_phases[s->phase]&0xF0)>0);
118-
qemu_set_irq(s->irq_enc_b, (encoder_input_phases[s->phase]&0x0F)>0);
116+
qemu_set_irq(s->irq_enc[0], (encoder_input_phases[s->phase]&0xF0)>0);
117+
qemu_set_irq(s->irq_enc[1], (encoder_input_phases[s->phase]&0x0F)>0);
119118
s->encoder_ticks--;
120119

121120
if (s->encoder_ticks>0)
@@ -171,8 +170,9 @@ static void encoder_input_reset(DeviceState *dev)
171170
InputState *s = ENCODER_INPUT(dev);
172171
s->last_state = 0;
173172
s->phase = 0;
174-
qemu_irq_lower(s->irq_enc_a);
175-
qemu_irq_lower(s->irq_enc_b);
173+
qemu_irq_raise(s->irq_enc_button);
174+
qemu_irq_raise(s->irq_enc[0]);
175+
qemu_irq_raise(s->irq_enc[1]);
176176
}
177177

178178
static int encoder_input_process_action(P404ScriptIF *obj, unsigned int action, script_args args)
@@ -204,8 +204,7 @@ static void encoder_input_init(Object *obj)
204204
{
205205
InputState *s = ENCODER_INPUT(obj);
206206
qdev_init_gpio_out_named(DEVICE(obj), &s->irq_enc_button, "encoder-button", 1);
207-
qdev_init_gpio_out_named(DEVICE(obj), &s->irq_enc_a, "encoder-a", 1);
208-
qdev_init_gpio_out_named(DEVICE(obj), &s->irq_enc_b, "encoder-b", 1);
207+
qdev_init_gpio_out_named(DEVICE(obj), s->irq_enc, "encoder-ab", 2);
209208
qdev_init_gpio_out_named(DEVICE(obj), s->cursor_xy, "cursor_xy", 2);
210209
qdev_init_gpio_out_named(DEVICE(obj), &s->tap, "touch", 1);
211210
qemu_add_mouse_event_handler(&encoder_input_mouseevent,ENCODER_INPUT(obj),false, "encoder-mouse");

hw/arm/prusa/parts/ws281x.c

+14-7
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,13 @@ struct WS281xState {
7070

7171
};
7272

73+
#define T0H_NS 350
74+
#define T1H_NS 700
75+
#define T0L_NS 800
76+
#define T1L_NS 600
77+
#define THRESH_NS 150
78+
#define RESET_NS 50000
79+
7380
OBJECT_DEFINE_TYPE_SIMPLE_WITH_INTERFACES(WS281xState, ws281x, WS281X, SYS_BUS_DEVICE, {NULL} );
7481

7582
// handler for chaining via din/dout - so only the first LED on the SPI bus needs to decode the bitpattern.
@@ -109,8 +116,8 @@ static void ws281x_gpio(void* opaque, int n, int level)
109116
}
110117
if (level)
111118
{
112-
s->last_highc = icount_get_raw();
113-
if (s->last_highc - s->last_lowc >15000)
119+
s->last_highc = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); //icount_get_raw();
120+
if (s->last_highc - s->last_lowc >= RESET_NS)
114121
{
115122
s->bit_count = 0;
116123
s->current_colour.raw = 0;
@@ -120,15 +127,15 @@ static void ws281x_gpio(void* opaque, int n, int level)
120127
}
121128
else
122129
{
123-
s->last_lowc = icount_get_raw();
130+
s->last_lowc = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); // icount_get_raw();
124131
if (s->last_lowc == 0)
125132
{
126-
printf("ERR: WS281x detected '-icount ' is not set. LED will not function without accurate timing!\n");
127-
s->disabled = true;
133+
// printf("ERR: WS281x detected '-icount ' is not set. LED will not function without accurate timing!\n");
134+
//s->disabled = true;
128135
}
129136
s->current_colour.raw <<= 1;
130-
s->current_colour.raw |= (s->last_lowc - s->last_highc) > 22; // This value is highly dependent on the value of icount. Tested with -icount 2 gets ns values close to correct in real ns
131-
// printf("last high: %d\n",(s->last_lowc - s->last_highc));
137+
s->current_colour.raw |= abs((s->last_lowc - s->last_highc) - T1H_NS) <= THRESH_NS; // This value is highly dependent on the value of icount. Tested with -icount 2 gets ns values close to correct in real ns
138+
// printf("last high: %ld\n",(s->last_lowc - s->last_highc));
132139
s->bit_count++;
133140
if (s->bit_count == 24)
134141
{

hw/arm/prusa/prusa-mini.c

+5-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* in the Software without restriction, including without limitation the rights
99
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1010
* copies of the Software, and to permit persons to whom the Software is
11-
* furnished to do so, subject to the following conditions:
11+
* furnished to do so, subject to the following conditions:d
1212
*
1313
* The above copyright notice and this permission notice shall be included in
1414
* all copies or substantial portions of the Software.
@@ -343,6 +343,7 @@ static void prusa_mini_init(MachineState *machine, const mini_config_t* cfg)
343343
for (int i=0; i<2; i++)
344344
{
345345
dev = qdev_new("fan");
346+
object_property_add_child(OBJECT(periphs), g_strdup_printf("fan-%c",fan_labels[i]), OBJECT(dev));
346347
qdev_prop_set_uint8(dev,"label",fan_labels[i]);
347348
qdev_prop_set_uint32(dev, "max_rpm",fan_max_rpms[i]);
348349
qdev_prop_set_bit(dev, "is_nonlinear", i); // E is nonlinear.
@@ -359,10 +360,11 @@ static void prusa_mini_init(MachineState *machine, const mini_config_t* cfg)
359360
}
360361

361362
dev = qdev_new("encoder-input");
363+
object_property_add_child(periphs, "encoder-input", OBJECT(dev));
362364
sysbus_realize(SYS_BUS_DEVICE(dev), &error_fatal);
363365
qdev_connect_gpio_out_named(dev, "encoder-button", 0, qdev_get_gpio_in(stm32_soc_get_periph(dev_soc, STM32_P_GPIOE),12));
364-
qdev_connect_gpio_out_named(dev, "encoder-a", 0, qdev_get_gpio_in(stm32_soc_get_periph(dev_soc, STM32_P_GPIOE),15));
365-
qdev_connect_gpio_out_named(dev, "encoder-b", 0, qdev_get_gpio_in(stm32_soc_get_periph(dev_soc, STM32_P_GPIOE),13));
366+
qdev_connect_gpio_out_named(dev, "encoder-ab", 0, qdev_get_gpio_in(stm32_soc_get_periph(dev_soc, STM32_P_GPIOE),15));
367+
qdev_connect_gpio_out_named(dev, "encoder-ab", 1, qdev_get_gpio_in(stm32_soc_get_periph(dev_soc, STM32_P_GPIOE),13));
366368

367369
// Needs to come last because it has the scripting engine setup.
368370
dev = qdev_new("p404-scriptcon");

hw/arm/prusa/prusa-mk4.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -783,8 +783,8 @@ static void mk4_init(MachineState *machine)
783783
DeviceState* encoder = qdev_new("encoder-input");
784784
sysbus_realize(SYS_BUS_DEVICE(encoder), &error_fatal);
785785
qdev_connect_gpio_out_named(encoder, "encoder-button", 0, qdev_get_gpio_in(stm32_soc_get_periph(dev_soc, BANK(cfg.enc_btn)), PIN(cfg.enc_btn)));
786-
qdev_connect_gpio_out_named(encoder, "encoder-a", 0, qdev_get_gpio_in(stm32_soc_get_periph(dev_soc, BANK(cfg.enc_a)), PIN(cfg.enc_a)));
787-
qdev_connect_gpio_out_named(encoder, "encoder-b", 0, qdev_get_gpio_in(stm32_soc_get_periph(dev_soc, BANK(cfg.enc_b)), PIN(cfg.enc_b)));
786+
qdev_connect_gpio_out_named(encoder, "encoder-ab", 0, qdev_get_gpio_in(stm32_soc_get_periph(dev_soc, BANK(cfg.enc_a)), PIN(cfg.enc_a)));
787+
qdev_connect_gpio_out_named(encoder, "encoder-ab", 1, qdev_get_gpio_in(stm32_soc_get_periph(dev_soc, BANK(cfg.enc_b)), PIN(cfg.enc_b)));
788788

789789
bus = qdev_get_child_bus(
790790
stm32_soc_get_periph(dev_soc, STM32_P_I2C3),

hw/arm/prusa/prusa-xl-bed.c

+3
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ static void prusa_xl_bed_init(MachineState *machine, int hw_type)
6363
{
6464
DeviceState *dev;
6565

66+
Object* periphs = container_get(OBJECT(machine), "/peripheral");
67+
6668
dev = qdev_new(TYPE_STM32G070xB_SOC);
6769
hwaddr FLASH_SIZE = stm32_soc_get_flash_size(dev);
6870

@@ -154,6 +156,7 @@ static void prusa_xl_bed_init(MachineState *machine, int hw_type)
154156
break;
155157
}
156158
DeviceState* mux = qdev_new("hc4052");
159+
object_property_add_child(periphs, "mux", OBJECT(mux));
157160
qdev_prop_set_uint8(mux, "start_channel",1);
158161

159162
sysbus_realize(SYS_BUS_DEVICE(mux), &error_fatal);

hw/arm/prusa/prusa-xl-extruder.c

+5
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ static void _prusa_xl_extruder_init(MachineState *machine, int index, int type)
100100
{
101101
DeviceState *dev;
102102

103+
Object* periphs = container_get(OBJECT(machine), "/peripheral");
104+
103105
const prusa_xl_e_cfg_t* cfg = extruder_cfg_map[type];
104106

105107
dev = qdev_new(TYPE_STM32G070xB_SOC);
@@ -187,11 +189,13 @@ static void _prusa_xl_extruder_init(MachineState *machine, int index, int type)
187189

188190
qdev_connect_gpio_out(stm32_soc_get_periph(dev_soc, STM32_P_GPIOC),11,qdev_get_gpio_in_named(dashboard, "led-digital",1));
189191
dev = qdev_new("dwarf-input");
192+
object_property_add_child(periphs, "dwarf-input", OBJECT(dev));
190193
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
191194
qdev_connect_gpio_out(dev,0,qdev_get_gpio_in(stm32_soc_get_periph(dev_soc, STM32_P_GPIOA),15));
192195
qdev_connect_gpio_out(dev,1,qdev_get_gpio_in(stm32_soc_get_periph(dev_soc, STM32_P_GPIOC),10));
193196

194197
dev = qdev_new("ws281x");
198+
object_property_add_child(periphs, "ws281x", OBJECT(dev));
195199
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
196200
qdev_connect_gpio_out(stm32_soc_get_periph(dev_soc, STM32_P_GPIOB),6,qdev_get_gpio_in(dev,0));
197201
qdev_connect_gpio_out_named(dev,"colour",0,qdev_get_gpio_in_named(dashboard, "led-rgb",0));
@@ -274,6 +278,7 @@ static void _prusa_xl_extruder_init(MachineState *machine, int index, int type)
274278
qdev_connect_gpio_out(lc,0, qdev_get_gpio_in_named(dev,"input_x1000",0));
275279

276280
DeviceState* mux = qdev_new("cbtl3257");
281+
object_property_add_child(periphs, "mux", OBJECT(mux));
277282
sysbus_realize_and_unref(SYS_BUS_DEVICE(mux), &error_fatal);
278283
qdev_connect_gpio_out(stm32_soc_get_periph(dev_soc, STM32_P_GPIOD), 4,qdev_get_gpio_in_named(mux,"select",0));
279284
qdev_connect_gpio_out(stm32_soc_get_periph(dev_soc, STM32_P_GPIOD), 0,qdev_get_gpio_in_named(mux,"B1",0));

hw/arm/prusa/prusa-xl.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -645,8 +645,8 @@ static void xl_init(MachineState *machine, xl_cfg_t cfg)
645645
DeviceState* encoder = qdev_new("encoder-input");
646646
sysbus_realize(SYS_BUS_DEVICE(encoder), &error_fatal);
647647
qdev_connect_gpio_out_named(encoder, "encoder-button", 0, qdev_get_gpio_in(stm32_soc_get_periph(dev_soc, BANK(cfg.enc_btn)), PIN(cfg.enc_btn)));
648-
qdev_connect_gpio_out_named(encoder, "encoder-a", 0, qdev_get_gpio_in(stm32_soc_get_periph(dev_soc, BANK(cfg.enc_a)), PIN(cfg.enc_a)));
649-
qdev_connect_gpio_out_named(encoder, "encoder-b", 0, qdev_get_gpio_in(stm32_soc_get_periph(dev_soc, BANK(cfg.enc_b)), PIN(cfg.enc_b)));
648+
qdev_connect_gpio_out_named(encoder, "encoder-ab", 0, qdev_get_gpio_in(stm32_soc_get_periph(dev_soc, BANK(cfg.enc_a)), PIN(cfg.enc_a)));
649+
qdev_connect_gpio_out_named(encoder, "encoder-ab", 1, qdev_get_gpio_in(stm32_soc_get_periph(dev_soc, BANK(cfg.enc_b)), PIN(cfg.enc_b)));
650650

651651
bus = qdev_get_child_bus(
652652
stm32_soc_get_periph(dev_soc, STM32_P_I2C3),

hw/arm/prusa/stm32_tests/meson.build

+7
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
qtests_buddy = [
2+
'prusa/stm32_tests/mini404_dwarf_input_test',
3+
'prusa/stm32_tests/mini404_encoder_test',
4+
'prusa/stm32_tests/mini404_fan_test',
25
'prusa/stm32_tests/mini404_irsensor_test',
6+
'prusa/stm32_tests/mini404_hx717_test',
37
'prusa/stm32_tests/mini404_hallsensor_test',
48
'prusa/stm32_tests/mini404_mmu_bridge_test',
59
'prusa/stm32_tests/mini404_pinda_test',
10+
'prusa/stm32_tests/mini404_sn74cbt_test',
11+
'prusa/stm32_tests/mini404_sn74hc4052_test',
12+
'prusa/stm32_tests/mini404_ws281x_test',
613
'prusa/stm32_tests/stm32_adc-test',
714
'prusa/stm32_tests/stm32_dbg-test',
815
'prusa/stm32_tests/stm32_crc-test',
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*
2+
mini404_dwarf_input_test.c - Test cases for the dwarf input peripheral.
3+
4+
Copyright (C) 2024 VintagePC <https://github.com/vintagepc>
5+
6+
This file is part of Mini404.
7+
8+
Mini404 is free software: you can redistribute it and/or modify
9+
it under the terms of the GNU General Public License as published by
10+
the Free Software Foundation, either version 3 of the License, or
11+
(at your option) any later version.
12+
13+
Mini404 is distributed in the hope that it will be useful,
14+
but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
GNU General Public License for more details.
17+
18+
You should have received a copy of the GNU General Public License
19+
along with Mini404. If not, see <http://www.gnu.org/licenses/>.
20+
*/
21+
22+
#include "qemu/osdep.h"
23+
#include "libqtest-single.h"
24+
25+
#define QOM_PATH "/machine/peripheral/dwarf-input"
26+
#define TEST_PREFIX "/mini404/parts/dward-input/"
27+
#define MACHINE "prusa-xl-extruder-040-0"
28+
29+
static void test_key_control(void)
30+
{
31+
/* Test code goes here */
32+
QTestState *ts = qtest_init("-machine " MACHINE);
33+
qtest_irq_intercept_out(ts, QOM_PATH);
34+
/* Assertions and other test logic */
35+
36+
g_free(qtest_hmp(ts, "system_reset"));
37+
38+
// Check start state
39+
g_assert_true(qtest_get_irq(ts, 0));
40+
g_assert_true(qtest_get_irq(ts, 1));
41+
42+
g_free(qtest_hmp(ts, "sendkey w"));
43+
g_assert_false(qtest_get_irq(ts, 0));
44+
g_assert_true(qtest_get_irq(ts, 1));
45+
46+
qtest_clock_step(ts, 101 * 1E6); // 100ms default hold-time
47+
g_assert_true(qtest_get_irq(ts, 0));
48+
g_assert_true(qtest_get_irq(ts, 1));
49+
50+
g_free(qtest_hmp(ts, "sendkey s"));
51+
52+
g_assert_true(qtest_get_irq(ts, 0));
53+
g_assert_false(qtest_get_irq(ts, 1));
54+
55+
qtest_clock_step(ts, 100 * 1E6); // 100ms default hold-time
56+
57+
g_assert_true(qtest_get_irq(ts, 0));
58+
g_assert_true(qtest_get_irq(ts, 1));
59+
60+
qtest_quit(ts);
61+
}
62+
63+
static void test_reset(void)
64+
{
65+
/* Test code goes here */
66+
QTestState *ts = qtest_init("-machine " MACHINE);
67+
qtest_irq_intercept_out(ts, QOM_PATH);
68+
/* Assertions and other test logic */
69+
70+
g_free(qtest_hmp(ts, "sendkey w"));
71+
g_assert_false(qtest_get_irq(ts, 0));
72+
73+
g_free(qtest_hmp(ts, "system_reset"));
74+
75+
g_assert_true(qtest_get_irq(ts, 0));
76+
g_assert_true(qtest_get_irq(ts, 1));
77+
// Apparently HMP can't send multiple keys at once, delay until it's cleared.
78+
qtest_clock_step_next(ts);
79+
qtest_clock_step_next(ts);
80+
qtest_clock_step_next(ts);
81+
g_free(qtest_hmp(ts, "sendkey s"));
82+
83+
g_assert_false(qtest_get_irq(ts, 1));
84+
85+
g_free(qtest_hmp(ts, "system_reset"));
86+
87+
g_assert_true(qtest_get_irq(ts, 1));
88+
89+
qtest_quit(ts);
90+
}
91+
92+
int main(int argc, char **argv)
93+
{
94+
g_test_init(&argc, &argv, NULL);
95+
g_test_set_nonfatal_assertions();
96+
97+
/* Add your test case to the test suite */
98+
qtest_add_func(TEST_PREFIX "keys", test_key_control);
99+
qtest_add_func(TEST_PREFIX "reset", test_reset);
100+
101+
/* Run the tests */
102+
return g_test_run();
103+
}

0 commit comments

Comments
 (0)