pwm_display: add support for multi-state outputs per brightness level

This commit is contained in:
hap 2022-02-25 19:51:30 +01:00
parent d196d072ff
commit fd45e9cfad
3 changed files with 53 additions and 75 deletions

View File

@ -15,8 +15,12 @@ or write_row to set them.
Display element states are sent to output tags "y.x" where y is the matrix row
number, x is the row bit. It is also sent to "y.a" for all rows. The output state
is 0 for off, and >0 for on, depending on brightness level. If segmask is defined,
it is also sent to "digity", for use with multi-state elements, eg. 7seg leds.
is 0 for off, and >0 for on, depending on brightness level.
If segmask is defined, it is also sent to "multiy.b" where b is brightness level,
for use with multi-state elements. This usecase is not common though (one example
is Coleco Quarterback where some digit segments are brighter). And when brightness
level does not matter, it is also sent to "digity", for common 7seg leds.
If you use this device in a slot, or use multiple of them (or just don't want
to use the default output tags), set a callback.
@ -25,9 +29,9 @@ Brightness tresholds (0.0 to 1.0) indicate how long an element was powered on
in the last frame, eg. 0.01 means a minimum on-time for 1%. Some games use two
levels of brightness by strobing elements longer.
TODO:
- SVG screens and rendlay digit elements don't support multiple brightness levels
- SVG screens and rendlay digit elements don't support multiple brightness levels,
the latter can be worked around with by stacking digits on top of eachother
*/
@ -47,9 +51,11 @@ pwm_display_device::pwm_display_device(const machine_config &mconfig, const char
device_t(mconfig, PWM_DISPLAY, tag, owner, clock),
m_out_x(*this, "%u.%u", 0U, 0U),
m_out_a(*this, "%u.a", 0U),
m_out_multi(*this, "multi%u.%u", 0U, 0U),
m_out_digit(*this, "digit%u", 0U),
m_output_x_cb(*this),
m_output_a_cb(*this),
m_output_multi_cb(*this),
m_output_digit_cb(*this)
{
// set defaults
@ -70,15 +76,17 @@ pwm_display_device::pwm_display_device(const machine_config &mconfig, const char
void pwm_display_device::device_start()
{
// resolve handlers
m_external_output = !m_output_x_cb.isnull() || !m_output_a_cb.isnull() || !m_output_digit_cb.isnull();
m_external_output = !m_output_x_cb.isnull() || !m_output_a_cb.isnull() || !m_output_multi_cb.isnull() || !m_output_digit_cb.isnull();
m_output_x_cb.resolve_safe();
m_output_a_cb.resolve_safe();
m_output_multi_cb.resolve_safe();
m_output_digit_cb.resolve_safe();
if (!m_external_output)
{
m_out_x.resolve();
m_out_a.resolve();
m_out_multi.resolve();
m_out_digit.resolve();
}
@ -191,13 +199,12 @@ TIMER_CALLBACK_MEMBER(pwm_display_device::frame_tick)
const double factor1 = 1.0 - factor0;
// determine brightness cutoff
u8 max_levels = 1;
for (; m_levels[max_levels] < 1.0; max_levels++) { ; }
double cutoff = m_level_max;
if (cutoff == 0.0)
{
u8 level;
for (level = 1; m_levels[level] < 1.0; level++) { ; }
cutoff = 4 * m_levels[level - 1];
}
cutoff = 4 * m_levels[max_levels - 1];
if (cutoff > 1.0)
cutoff = 1.0;
@ -205,7 +212,8 @@ TIMER_CALLBACK_MEMBER(pwm_display_device::frame_tick)
for (int y = 0; y < m_height; y++)
{
u64 row = 0;
u64 multi_row[0x40];
std::fill(std::begin(multi_row), std::end(multi_row), 0);
for (int x = 0; x <= m_width; x++)
{
@ -221,8 +229,7 @@ TIMER_CALLBACK_MEMBER(pwm_display_device::frame_tick)
// output to y.x, or y.a when always-on
if (x != m_width)
{
if (level > m_level_min)
row |= (u64(1) << x);
multi_row[level] |= (u64(1) << x);
if (m_external_output)
m_output_x_cb(x << 6 | y, level);
@ -238,15 +245,29 @@ TIMER_CALLBACK_MEMBER(pwm_display_device::frame_tick)
}
}
// output to digity (does not support multiple brightness levels)
// multi-state outputs
if (m_segmask[y] != 0)
{
row &= m_segmask[y];
u64 digit_row = 0;
for (int b = 0; b <= max_levels; b++)
{
multi_row[b] &= m_segmask[y];
if (b > m_level_min)
digit_row |= multi_row[b];
// output to multiy.b
if (m_external_output)
m_output_multi_cb(b << 6 | y, digit_row);
else
m_out_multi[y][b] = multi_row[b];
}
// output to digity (single brightness level)
if (m_external_output)
m_output_digit_cb(y, row);
m_output_digit_cb(y, digit_row);
else
m_out_digit[y] = row;
m_out_digit[y] = digit_row;
}
}

View File

@ -29,6 +29,7 @@ public:
// output callbacks when not using the default output tags
auto output_x() { return m_output_x_cb.bind(); } // x = offset >> 6, y = offset & 0x3f
auto output_a() { return m_output_a_cb.bind(); }
auto output_multi() { return m_output_multi_cb.bind(); } // b = offset >> 6, y = offset & 0x3f
auto output_digit() { return m_output_digit_cb.bind(); }
void reset_bri_levels() { std::fill(std::begin(m_levels), std::end(m_levels), 1.0); }
@ -68,10 +69,12 @@ protected:
private:
output_finder<0x40, 0x40> m_out_x;
output_finder<0x40> m_out_a;
output_finder<0x40, 0x40> m_out_multi;
output_finder<0x40> m_out_digit;
devcb_write8 m_output_x_cb;
devcb_write8 m_output_a_cb;
devcb_write64 m_output_multi_cb;
devcb_write64 m_output_digit_cb;
bool m_external_output;

View File

@ -57,15 +57,15 @@ license:CC0
</element>
<element name="digit" defstate="0">
<led7seg><color red="1.0" green="0.25" blue="0.26" /></led7seg>
<led7seg alpha="0.0833"><color red="1.0" green="0.25" blue="0.26" /></led7seg>
</element>
<element name="seg" defstate="0">
<rect state="0"><color red="0.13" green="0.0325" blue="0.0338" /></rect>
<rect state="1"><color red="0.5" green="0.125" blue="0.13" /></rect>
<rect state="2"><color red="1.0" green="0.25" blue="0.26" /></rect>
</element>
<element name="mask" defstate="0">
<disk state="1"><color red="0" green="0" blue="0" /></disk>
<element name="mask">
<rect><color red="0" green="0" blue="0" /></rect>
</element>
@ -141,62 +141,16 @@ license:CC0
<element ref="static_white"><bounds x="344" y="56" width="4" height="1" /></element>
<!-- leds -->
<element name="digit0" ref="digit"><bounds x="3" y="-15.5" width="24" height="32" /></element>
<element name="0.8" ref="seg"><bounds x="7" y="42.5" width="15" height="3" /></element>
<element name="0.9" ref="seg"><bounds x="7" y="71.5" width="15" height="3" /></element>
<repeat count="9">
<param name="xd" start="3" increment="44" />
<param name="xs" start="7" increment="44" />
<param name="i" start="0" increment="1" />
<element name="digit1" ref="digit"><bounds x="47" y="-15.5" width="24" height="32" /></element>
<element name="1.8" ref="seg"><bounds x="51" y="42.5" width="15" height="3" /></element>
<element name="1.9" ref="seg"><bounds x="51" y="71.5" width="15" height="3" /></element>
<element name="digit2" ref="digit"><bounds x="91" y="-15.5" width="24" height="32" /></element>
<element name="2.8" ref="seg"><bounds x="95" y="42.5" width="15" height="3" /></element>
<element name="2.9" ref="seg"><bounds x="95" y="71.5" width="15" height="3" /></element>
<element name="digit3" ref="digit"><bounds x="135" y="-15.5" width="24" height="32" /></element>
<element name="3.8" ref="seg"><bounds x="139" y="42.5" width="15" height="3" /></element>
<element name="3.9" ref="seg"><bounds x="139" y="71.5" width="15" height="3" /></element>
<element name="digit4" ref="digit"><bounds x="179" y="-15.5" width="24" height="32" /></element>
<element name="4.8" ref="seg"><bounds x="183" y="42.5" width="15" height="3" /></element>
<element name="4.9" ref="seg"><bounds x="183" y="71.5" width="15" height="3" /></element>
<element name="digit5" ref="digit"><bounds x="223" y="-15.5" width="24" height="32" /></element>
<element name="5.8" ref="seg"><bounds x="227" y="42.5" width="15" height="3" /></element>
<element name="5.9" ref="seg"><bounds x="227" y="71.5" width="15" height="3" /></element>
<element name="digit6" ref="digit"><bounds x="267" y="-15.5" width="24" height="32" /></element>
<element name="6.8" ref="seg"><bounds x="271" y="42.5" width="15" height="3" /></element>
<element name="6.9" ref="seg"><bounds x="271" y="71.5" width="15" height="3" /></element>
<element name="digit7" ref="digit"><bounds x="311" y="-15.5" width="24" height="32" /></element>
<element name="7.8" ref="seg"><bounds x="315" y="42.5" width="15" height="3" /></element>
<element name="7.9" ref="seg"><bounds x="315" y="71.5" width="15" height="3" /></element>
<element name="digit8" ref="digit"><bounds x="355" y="-15.5" width="24" height="32" /></element>
<element name="8.8" ref="seg"><bounds x="359" y="42.5" width="15" height="3" /></element>
<element name="8.9" ref="seg"><bounds x="359" y="71.5" width="15" height="3" /></element>
<!-- digit masks -->
<element name="0.0" ref="mask"><bounds x="8" y="-17" width="17" height="6" /><color alpha="0.5" /></element>
<element name="1.0" ref="mask"><bounds x="52" y="-17" width="17" height="6" /><color alpha="0.5" /></element>
<element name="2.0" ref="mask"><bounds x="96" y="-17" width="17" height="6" /><color alpha="0.5" /></element>
<element name="3.0" ref="mask"><bounds x="140" y="-17" width="17" height="6" /><color alpha="0.5" /></element>
<element name="4.0" ref="mask"><bounds x="184" y="-17" width="17" height="6" /><color alpha="0.5" /></element>
<element name="5.0" ref="mask"><bounds x="228" y="-17" width="17" height="6" /><color alpha="0.5" /></element>
<element name="6.0" ref="mask"><bounds x="272" y="-17" width="17" height="6" /><color alpha="0.5" /></element>
<element name="7.0" ref="mask"><bounds x="316" y="-17" width="17" height="6" /><color alpha="0.5" /></element>
<element name="8.0" ref="mask"><bounds x="360" y="-17" width="17" height="6" /><color alpha="0.5" /></element>
<element name="0.3" ref="mask"><bounds x="5" y="12" width="17" height="6" /><color alpha="0.5" /></element>
<element name="1.3" ref="mask"><bounds x="49" y="12" width="17" height="6" /><color alpha="0.5" /></element>
<element name="2.3" ref="mask"><bounds x="93" y="12" width="17" height="6" /><color alpha="0.5" /></element>
<element name="3.3" ref="mask"><bounds x="137" y="12" width="17" height="6" /><color alpha="0.5" /></element>
<element name="4.3" ref="mask"><bounds x="181" y="12" width="17" height="6" /><color alpha="0.5" /></element>
<element name="5.3" ref="mask"><bounds x="225" y="12" width="17" height="6" /><color alpha="0.5" /></element>
<element name="6.3" ref="mask"><bounds x="269" y="12" width="17" height="6" /><color alpha="0.5" /></element>
<element name="7.3" ref="mask"><bounds x="313" y="12" width="17" height="6" /><color alpha="0.5" /></element>
<element name="8.3" ref="mask"><bounds x="357" y="12" width="17" height="6" /><color alpha="0.5" /></element>
<element name="multi~i~.1" ref="digit"><bounds x="~xd~" y="-15.5" width="24" height="32" /><color alpha="0.5" /></element>
<element name="multi~i~.2" ref="digit"><bounds x="~xd~" y="-15.5" width="24" height="32" /></element>
<element name="~i~.8" ref="seg"><bounds x="~xs~" y="42.5" width="15" height="3" /></element>
<element name="~i~.9" ref="seg"><bounds x="~xs~" y="71.5" width="15" height="3" /></element>
</repeat>
</view>
</mamelayout>