summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/em_reel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/em_reel.cpp')
-rw-r--r--src/devices/machine/em_reel.cpp125
1 files changed, 125 insertions, 0 deletions
diff --git a/src/devices/machine/em_reel.cpp b/src/devices/machine/em_reel.cpp
new file mode 100644
index 00000000000..392c9331818
--- /dev/null
+++ b/src/devices/machine/em_reel.cpp
@@ -0,0 +1,125 @@
+// license:BSD-3-Clause
+// copyright-holders:SomeRandomGuyIdk
+/**********************************************************************
+
+ Electromechanical reels for slot machines
+
+**********************************************************************/
+
+#include "emu.h"
+#include "em_reel.h"
+
+#include <algorithm>
+
+
+ALLOW_SAVE_TYPE(em_reel_device::dir);
+ALLOW_SAVE_TYPE(em_reel_device::reel_state);
+
+DEFINE_DEVICE_TYPE(EM_REEL, em_reel_device, "em_reel", "Electromechanical Reel")
+
+em_reel_device::em_reel_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, EM_REEL, tag, owner, clock),
+ m_reel_out(*this, tag),
+ m_state_cb(*this)
+{
+}
+
+void em_reel_device::set_state(uint8_t state)
+{
+ if(m_state == reel_state::STOPPED)
+ {
+ if(state)
+ {
+ m_state = reel_state::SPINNING;
+ m_move_timer->adjust(m_step_period);
+ m_state_cb(1);
+ }
+ }
+ else if(m_state == reel_state::SPINNING)
+ {
+ if(!state)
+ {
+ if(is_at_detent()) // If reel is already on a detent, then stop it immediately
+ {
+ m_move_timer->adjust(attotime::never);
+ m_state = reel_state::STOPPED;
+ m_state_cb(0);
+ }
+ else
+ {
+ m_state = reel_state::STOPPING;
+ }
+ }
+ }
+ else if(m_state == reel_state::STOPPING)
+ {
+ if(state)
+ m_state = reel_state::SPINNING;
+ }
+}
+
+inline bool em_reel_device::is_at_detent() const
+{
+ auto const found = std::lower_bound(m_detents.begin(), m_detents.end(), m_pos);
+ return (m_detents.end() != found) && (*found == m_pos);
+}
+
+TIMER_CALLBACK_MEMBER( em_reel_device::move )
+{
+ if(m_direction == dir::REVERSE)
+ {
+ if(m_pos == 0)
+ m_pos = m_max_pos;
+ else
+ m_pos--;
+ }
+ else
+ {
+ if(m_pos == m_max_pos)
+ m_pos = 0;
+ else
+ m_pos++;
+ }
+
+ if(m_state == reel_state::STOPPING && is_at_detent()) // Stop once a detent is reached
+ {
+ m_state = reel_state::STOPPED;
+ m_state_cb(0);
+ }
+ else
+ {
+ m_move_timer->adjust(m_step_period);
+ }
+
+ m_reel_out = m_pos;
+}
+
+void em_reel_device::device_start()
+{
+ m_reel_out.resolve();
+
+ save_item(NAME(m_state));
+ save_item(NAME(m_pos));
+ save_item(NAME(m_direction));
+
+ m_move_timer = timer_alloc(FUNC(em_reel_device::move), this);
+
+ m_state = reel_state::STOPPED;
+ m_pos = 0;
+}
+
+void em_reel_device::device_validity_check(validity_checker &valid) const
+{
+ auto detent = m_detents.begin();
+ while(m_detents.end() != detent)
+ {
+ if(*detent > m_max_pos)
+ fatalerror("Detent on step %u is out of range, maximum is %u\n", *detent, m_max_pos);
+
+ auto const next = std::next(detent);
+ if((m_detents.end() != next) && (*next <= *detent))
+ fatalerror("Detents %u and %u are not in ascending order\n", *detent, *next);
+
+ detent = next;
+ }
+}