452 static int preamble_count = 0;
453 static BitEnum last_bit = DCC_ONE;
454 static int count = 0;
455 static int packet_repeat_count = 0;
456 static int bit_repeat_count = 0;
458 static bool resync =
true;
460 bool get_next_packet =
false;
462 MAP_TimerIntClear(HW::INTERVAL_BASE, TIMER_TIMA_TIMEOUT);
470 current_bit = MM_PREAMBLE;
471 state_ = ST_MM_PREAMBLE;
481 current_bit = DCC_ONE;
484 int preamble_needed = HW::dcc_preamble_count() - 1;
485 if (HW::generate_railcom_halfzero() &&
488 if (preamble_count == 0)
490 current_bit = DCC_RC_HALF_ZERO;
496 preamble_needed = 21;
498 if (++preamble_count >= preamble_needed)
506 current_bit = DCC_ZERO;
519 uint8_t bit = (packet->
payload[count] >> (DATA_7 - state_)) & 0x01;
520 current_bit =
static_cast<BitEnum>(DCC_ZERO + bit);
521 state_ =
static_cast<State>(
static_cast<int>(state_) + 1);
525 if (++count >= packet->
dlc)
527 current_bit = DCC_RC_ONE;
528 state_ = DCC_MAYBE_RAILCOM;
533 current_bit = DCC_ZERO;
537 case DCC_MAYBE_RAILCOM:
539 (HW::Output1::need_railcom_cutout() ||
540 HW::Output2::need_railcom_cutout() ||
541 HW::Output3::need_railcom_cutout()))
543 current_bit = DCC_RC_ONE;
547 MAP_TimerLoadSet(HW::INTERVAL_BASE, TIMER_A,
548 timings[RAILCOM_CUTOUT_PRE].interval_period);
549 state_ = DCC_CUTOUT_PRE;
553 railcomDriver_->no_cutout();
554 current_bit = DCC_ONE;
555 state_ = DCC_NO_CUTOUT;
559 current_bit = DCC_ONE;
563 if (preamble_count >= 4)
565 current_bit = DCC_EOP_ONE;
567 if (preamble_count >= 5)
571 get_next_packet =
true;
575 current_bit = DCC_RC_ONE;
579 MAP_TimerLoadSet(HW::INTERVAL_BASE, TIMER_A,
580 timings[RAILCOM_CUTOUT_FIRST].interval_period);
581 state_ = DCC_START_RAILCOM_RECEIVE;
583 case DCC_START_RAILCOM_RECEIVE:
585 bool rc1 = HW::Output1::need_railcom_cutout();
586 bool rc2 = HW::Output2::need_railcom_cutout();
587 bool rc3 = HW::Output3::need_railcom_cutout();
593 std::max(delay, HW::Output1::start_railcom_cutout_phase1());
594 HW::Output1::isRailcomCutoutActive_ = 1;
599 std::max(delay, HW::Output2::start_railcom_cutout_phase1());
600 HW::Output2::isRailcomCutoutActive_ = 1;
605 std::max(delay, HW::Output3::start_railcom_cutout_phase1());
606 HW::Output3::isRailcomCutoutActive_ = 1;
611 MAP_SysCtlDelay(usecDelay_ * delay);
618 std::max(delay, HW::Output1::start_railcom_cutout_phase2());
623 std::max(delay, HW::Output2::start_railcom_cutout_phase2());
628 std::max(delay, HW::Output3::start_railcom_cutout_phase2());
633 MAP_SysCtlDelay(usecDelay_ * delay);
636 railcomDriver_->start_cutout();
638 current_bit = DCC_RC_ONE;
639 MAP_TimerLoadSet(HW::INTERVAL_BASE, TIMER_A,
640 timings[RAILCOM_CUTOUT_SECOND].interval_period);
641 state_ = DCC_MIDDLE_RAILCOM_CUTOUT;
644 case DCC_MIDDLE_RAILCOM_CUTOUT:
645 railcomDriver_->middle_cutout();
646 current_bit = DCC_RC_ONE;
647 MAP_TimerLoadSet(HW::INTERVAL_BASE, TIMER_A,
648 timings[RAILCOM_CUTOUT_POST].interval_period);
649 state_ = DCC_STOP_RAILCOM_RECEIVE;
651 case DCC_STOP_RAILCOM_RECEIVE:
653 current_bit = RAILCOM_CUTOUT_POST;
657 get_next_packet =
true;
658 railcomDriver_->end_cutout();
660 if (HW::Output1::isRailcomCutoutActive_)
663 std::max(delay, HW::Output1::stop_railcom_cutout_phase1());
665 if (HW::Output2::isRailcomCutoutActive_)
668 std::max(delay, HW::Output2::stop_railcom_cutout_phase1());
670 if (HW::Output3::isRailcomCutoutActive_)
673 std::max(delay, HW::Output3::stop_railcom_cutout_phase1());
678 MAP_SysCtlDelay(usecDelay_ * delay);
680 if (HW::Output1::isRailcomCutoutActive_)
682 HW::Output1::stop_railcom_cutout_phase2();
684 HW::Output1::isRailcomCutoutActive_ = 0;
685 if (HW::Output2::isRailcomCutoutActive_)
687 HW::Output2::stop_railcom_cutout_phase2();
689 HW::Output2::isRailcomCutoutActive_ = 0;
690 if (HW::Output3::isRailcomCutoutActive_)
692 HW::Output3::stop_railcom_cutout_phase2();
694 HW::Output3::isRailcomCutoutActive_ = 0;
695 check_and_enable_outputs();
699 current_bit = MM_PREAMBLE;
701 if (preamble_count == 7 ||
702 preamble_count == 7 + 6 ||
703 preamble_count == 7 + 6 + 10 ||
704 preamble_count == 7 + 6 + 10 + 6)
712 railcomDriver_->no_cutout();
713 current_bit = MM_PREAMBLE;
714 if (++preamble_count >= 2) {
715 get_next_packet =
true;
727 (packet->
payload[count] >> (MM_DATA_7 - state_)) & 0x01;
728 current_bit =
static_cast<BitEnum>(MM_ZERO + bit);
729 state_ =
static_cast<State>(
static_cast<int>(state_) + 1);
735 (packet->
payload[count] >> (MM_DATA_7 - state_)) & 0x01;
736 current_bit =
static_cast<BitEnum>(MM_ZERO + bit);
739 state_ = ST_MM_PREAMBLE;
740 }
else if (count >= packet->
dlc) {
748 case POWER_IMM_TURNON:
749 current_bit = DCC_ONE;
750 packet_repeat_count = 0;
751 get_next_packet =
true;
758 TDebug::Resync::toggle();
759 auto* timing = &timings[current_bit];
762 HWREG(HW::CCP_BASE + TIMER_O_TAMR) &=
763 ~(TIMER_TAMR_TAMRSU | TIMER_TAMR_TAILD);
764 HWREG(HW::CCP_BASE + TIMER_O_TBMR) &=
765 ~(TIMER_TBMR_TBMRSU | TIMER_TBMR_TBILD);
766 HWREG(HW::INTERVAL_BASE + TIMER_O_TAMR) &=
767 ~(TIMER_TAMR_TAMRSU | TIMER_TAMR_TAILD);
771 HWREG(HW::INTERVAL_BASE + TIMER_O_TAILR) =
772 timing->interval_period + hDeadbandDelay_ * 2;
774 if (!HW::H_DEADBAND_DELAY_NSEC)
776 TDebug::Resync::toggle();
777 MAP_TimerDisable(HW::CCP_BASE, TIMER_A|TIMER_B);
779 MAP_TimerLoadSet(HW::CCP_BASE, TIMER_A|TIMER_B, timing->period);
780 MAP_TimerMatchSet(HW::CCP_BASE, TIMER_A, timing->transition_a);
781 MAP_TimerMatchSet(HW::CCP_BASE, TIMER_B, timing->transition_b);
782 MAP_TimerEnable(HW::CCP_BASE, TIMER_A | TIMER_B);
784 MAP_TimerDisable(HW::INTERVAL_BASE, TIMER_A);
786 HW::INTERVAL_BASE, TIMER_A, timing->interval_period);
787 MAP_TimerEnable(HW::INTERVAL_BASE, TIMER_A);
788 TDebug::Resync::toggle();
791 HWREG(HW::CCP_BASE + TIMER_O_TAMR) |=
792 (TIMER_TAMR_TAMRSU | TIMER_TAMR_TAILD);
793 HWREG(HW::CCP_BASE + TIMER_O_TBMR) |=
794 (TIMER_TBMR_TBMRSU | TIMER_TBMR_TBILD);
795 HWREG(HW::INTERVAL_BASE + TIMER_O_TAMR) |=
796 (TIMER_TAMR_TAMRSU | TIMER_TAMR_TAILD);
801 HWREG(HW::CCP_BASE + TIMER_O_TBMATCHR) =
802 timing->transition_b;
805 HWREG(HW::CCP_BASE + TIMER_O_TAMATCHR) = hDeadbandDelay_;
806 HWREG(HW::CCP_BASE + TIMER_O_TBILR) = timing->period;
807 HWREG(HW::CCP_BASE + TIMER_O_TAILR) = hDeadbandDelay_;
811 HWREG(TIMER0_BASE + TIMER_O_SYNC) = HW::TIMER_SYNC;
815 HWREG(HW::CCP_BASE + TIMER_O_TAMR) |=
816 (TIMER_TAMR_TAMRSU | TIMER_TAMR_TAILD);
817 HWREG(HW::CCP_BASE + TIMER_O_TBMR) |=
818 (TIMER_TBMR_TBMRSU | TIMER_TBMR_TBILD);
819 HWREG(HW::INTERVAL_BASE + TIMER_O_TAMR) |=
820 (TIMER_TAMR_TAMRSU | TIMER_TAMR_TAILD);
823 MAP_TimerLoadSet(HW::CCP_BASE, TIMER_A, timing->period);
824 MAP_TimerMatchSet(HW::CCP_BASE, TIMER_A, timing->transition_a);
826 HW::INTERVAL_BASE, TIMER_A, timing->interval_period);
829 last_bit = current_bit;
830 bit_repeat_count = 0;
831 if (current_bit == RAILCOM_CUTOUT_POST)
838 else if (current_bit == DCC_RC_HALF_ZERO)
842 current_bit = DCC_ONE;
845 if (bit_repeat_count >= 4)
848 last_bit = NUM_TIMINGS;
850 if (last_bit != current_bit)
852 auto* timing = &timings[current_bit];
857 spread = timing->spread_max - timing->spread_min;
861 spread = (seed_ % spread) + timing->spread_min;
863 MAP_TimerLoadSet(HW::INTERVAL_BASE, TIMER_A,
864 timing->interval_period + (spread << 1));
865 MAP_TimerLoadSet(HW::CCP_BASE, TIMER_A, timing->period + (spread << 1));
866 MAP_TimerLoadSet(HW::CCP_BASE, TIMER_B, timing->period + (spread << 1));
867 MAP_TimerMatchSet(HW::CCP_BASE, TIMER_A, timing->transition_a + spread);
868 MAP_TimerMatchSet(HW::CCP_BASE, TIMER_B, timing->transition_b + spread);
869 last_bit = current_bit;
870 bit_repeat_count = 0;
879 check_and_enable_outputs();
880 TDebug::NextPacket::toggle();
881 if (packet_repeat_count) {
882 --packet_repeat_count;
884 if (packet != &IDLE_PKT && packet_repeat_count == 0)
886 packetQueue_.increment_front();
888 MAP_IntPendSet(HW::OS_INTERRUPT);
892 if (!packetQueue_.empty())
894 packet = &packetQueue_.front();
904 if (!packet_repeat_count) {
905 packet_repeat_count = packet->packet_header.
rept_count + 1;
909 if (resync || !packet->packet_header.
is_marklin) {
912 state_ = ST_MM_PREAMBLE;
970 , writableNotifiable_(nullptr)
971 , railcomDriver_(railcom_driver)
1011 DCC_EOP_ONE, (56 << 1) + 20, 56, (56 << 1) - HW::RESYNC_DELAY_USEC);
1018 unsigned h_deadband = 2 * (HW::H_DEADBAND_DELAY_NSEC / 1000);
1019 unsigned railcom_part = 0;
1023 railcom_part = target;
1027 railcom_part = target;
1031 railcom_part = target;
1033 static_assert((5 * 56 * 2 - 56 + HW::RAILCOM_CUTOUT_POST_DELTA_USEC) >
1035 "railcom cutout too long");
1036 target = 5 * 56 * 2 - 56 + HW::RAILCOM_CUTOUT_POST_DELTA_USEC;
1037 unsigned remaining_high = target - railcom_part;
1042 remaining_high + 56 + h_deadband +
1043 HW::RAILCOM_CUTOUT_POST_NEGATIVE_DELTA_USEC);
1046 MAP_TimerDisable(HW::CCP_BASE, TIMER_A);
1047 MAP_TimerDisable(HW::CCP_BASE, TIMER_B);
1050 MAP_TimerClockSourceSet(HW::CCP_BASE, TIMER_CLOCK_SYSTEM);
1051 MAP_TimerClockSourceSet(HW::INTERVAL_BASE, TIMER_CLOCK_SYSTEM);
1053 MAP_TimerConfigure(HW::CCP_BASE, TIMER_CFG_SPLIT_PAIR |
1056 MAP_TimerControlStall(HW::CCP_BASE, TIMER_BOTH,
true);
1062 HWREG(HW::CCP_BASE + TIMER_O_TAMR) |=
1063 TIMER_TAMR_TAPLO | TIMER_TAMR_TAMRSU | TIMER_TAMR_TAILD;
1064 HWREG(HW::CCP_BASE + TIMER_O_TBMR) |=
1065 TIMER_TBMR_TBPLO | TIMER_TBMR_TBMRSU | TIMER_TBMR_TBILD;
1067 HWREG(HW::INTERVAL_BASE + TIMER_O_TAMR) |=
1068 TIMER_TAMR_TAMRSU | TIMER_TAMR_TAILD;
1070 MAP_TimerConfigure(HW::INTERVAL_BASE, TIMER_CFG_SPLIT_PAIR |
1071 TIMER_CFG_A_PERIODIC);
1072 MAP_TimerControlStall(HW::INTERVAL_BASE, TIMER_A,
true);
1074 MAP_TimerControlLevel(HW::CCP_BASE, TIMER_A, HW::PIN_H_INVERT);
1075 MAP_TimerControlLevel(HW::CCP_BASE, TIMER_B, !HW::PIN_L_INVERT);
1077 MAP_TimerLoadSet(HW::CCP_BASE, TIMER_A,
timings[
DCC_ONE].period);
1080 MAP_TimerMatchSet(HW::CCP_BASE, TIMER_A,
timings[
DCC_ONE].transition_a);
1081 MAP_TimerMatchSet(HW::CCP_BASE, TIMER_B,
timings[
DCC_ONE].transition_b);
1083 MAP_IntDisable(HW::INTERVAL_INTERRUPT);
1084 MAP_IntPrioritySet(HW::INTERVAL_INTERRUPT, 0x20);
1085 MAP_TimerIntEnable(HW::INTERVAL_BASE, TIMER_TIMA_TIMEOUT);
1087 MAP_TimerEnable(HW::CCP_BASE, TIMER_A);
1088 MAP_TimerEnable(HW::CCP_BASE, TIMER_B);
1089 MAP_TimerEnable(HW::INTERVAL_BASE, TIMER_A);
1092 MAP_TimerSynchronize(TIMER0_BASE, HW::TIMER_SYNC);
1095 MAP_TimerLoadSet(HW::CCP_BASE, TIMER_B,
timings[
DCC_ONE].period);
1098 MAP_IntEnable(HW::INTERVAL_INTERRUPT);
1101 MAP_TimerIntDisable(HW::CCP_BASE, 0xFFFFFFFF);
1103 MAP_IntPrioritySet(HW::OS_INTERRUPT, configKERNEL_INTERRUPT_PRIORITY);
1104 MAP_IntEnable(HW::OS_INTERRUPT);