Initial public release of SystemK.
This commit is contained in:
parent
387f57cdda
commit
6f51f5b006
129 changed files with 11654 additions and 2 deletions
218
Protocols/Nerf_Laser_Ops_Pro.c
Executable file
218
Protocols/Nerf_Laser_Ops_Pro.c
Executable file
|
@ -0,0 +1,218 @@
|
|||
|
||||
/*
|
||||
* This program source code file is part of SystemK, a library in the KTag project.
|
||||
*
|
||||
* 🛡️ <https://ktag.clubk.club> 🃞
|
||||
*
|
||||
* Copyright © 2016-2025 Joseph P. Kearney and the KTag developers.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under
|
||||
* the terms of the GNU Affero General Public License as published by the Free
|
||||
* Software Foundation, either version 3 of the License, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
* details.
|
||||
*
|
||||
* There should be a copy of the GNU Affero General Public License in the LICENSE
|
||||
* file in the root of this repository. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "SystemK.h"
|
||||
|
||||
#define NERF_RED_TEAM 0b00
|
||||
#define NERF_BLUE_TEAM 0b01
|
||||
#define NERF_PURPLE_TEAM 0b10
|
||||
|
||||
#define RED_TEAM_PACKET_DATA 0x0010
|
||||
#define BLUE_TEAM_PACKET_DATA 0x0210
|
||||
#define PURPLE_TEAM_PACKET_DATA 0x0110
|
||||
|
||||
#define NERF_LASER_OPS_PRO_HEADER_MARK_DURATION_IN_us 3000
|
||||
#define NERF_LASER_OPS_PRO_HEADER_SPACE_DURATION_IN_us 6000
|
||||
#define NERF_LASER_OPS_PRO_SPACE_DURATION_IN_us 2000
|
||||
#define NERF_LASER_OPS_PRO_MARK_ZERO_DURATION_IN_us 800
|
||||
#define NERF_LASER_OPS_PRO_MARK_ONE_DURATION_IN_us 2000
|
||||
#define NERF_LASER_OPS_PRO_TOLERANCE_IN_us 400
|
||||
|
||||
#define MIN_SPACE_IN_us (NERF_LASER_OPS_PRO_SPACE_DURATION_IN_us - NERF_LASER_OPS_PRO_TOLERANCE_IN_us)
|
||||
#define MAX_SPACE_IN_us (NERF_LASER_OPS_PRO_SPACE_DURATION_IN_us + NERF_LASER_OPS_PRO_TOLERANCE_IN_us)
|
||||
#define MIN_MARK_ZERO_IN_us (NERF_LASER_OPS_PRO_MARK_ZERO_DURATION_IN_us - NERF_LASER_OPS_PRO_TOLERANCE_IN_us)
|
||||
#define MAX_MARK_ZERO_IN_us (NERF_LASER_OPS_PRO_MARK_ZERO_DURATION_IN_us + NERF_LASER_OPS_PRO_TOLERANCE_IN_us)
|
||||
#define MIN_MARK_ONE_IN_us (NERF_LASER_OPS_PRO_MARK_ONE_DURATION_IN_us - NERF_LASER_OPS_PRO_TOLERANCE_IN_us)
|
||||
#define MAX_MARK_ONE_IN_us (NERF_LASER_OPS_PRO_MARK_ONE_DURATION_IN_us + NERF_LASER_OPS_PRO_TOLERANCE_IN_us)
|
||||
|
||||
static const TimedBit_T NERF_LASER_OPS_PRO_HEADER_MARK = {.symbol = MARK, .duration = NERF_LASER_OPS_PRO_HEADER_MARK_DURATION_IN_us};
|
||||
static const TimedBit_T NERF_LASER_OPS_PRO_HEADER_SPACE = {.symbol = SPACE, .duration = NERF_LASER_OPS_PRO_HEADER_SPACE_DURATION_IN_us};
|
||||
static const TimedBit_T NERF_LASER_OPS_PRO_SPACE = {.symbol = SPACE, .duration = NERF_LASER_OPS_PRO_SPACE_DURATION_IN_us};
|
||||
static const TimedBit_T NERF_LASER_OPS_PRO_ONE = {.symbol = MARK, .duration = NERF_LASER_OPS_PRO_MARK_ONE_DURATION_IN_us};
|
||||
static const TimedBit_T NERF_LASER_OPS_PRO_ZERO = {.symbol = MARK, .duration = NERF_LASER_OPS_PRO_MARK_ZERO_DURATION_IN_us};
|
||||
static const TimedBit_T NERF_LASER_OPS_PRO_END = {.symbol = SPACE, .duration = LAST_PULSE};
|
||||
|
||||
static TimedPulseTrain_T Tag_Send_Buffer;
|
||||
static DecodedPacket_T Nerf_Laser_Ops_Pro_Tag_Received_Buffers[3] =
|
||||
{
|
||||
{.Tag.type = DECODED_PACKET_TYPE_BUFFER_FREE},
|
||||
{.Tag.type = DECODED_PACKET_TYPE_BUFFER_FREE},
|
||||
{.Tag.type = DECODED_PACKET_TYPE_BUFFER_FREE}};
|
||||
|
||||
static inline DecodedPacket_T *Get_Tag_Packet_Buffer(void)
|
||||
{
|
||||
if (Nerf_Laser_Ops_Pro_Tag_Received_Buffers[0].Tag.type == DECODED_PACKET_TYPE_BUFFER_FREE)
|
||||
{
|
||||
return &Nerf_Laser_Ops_Pro_Tag_Received_Buffers[0];
|
||||
}
|
||||
else if (Nerf_Laser_Ops_Pro_Tag_Received_Buffers[1].Tag.type == DECODED_PACKET_TYPE_BUFFER_FREE)
|
||||
{
|
||||
return &Nerf_Laser_Ops_Pro_Tag_Received_Buffers[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Just use it.
|
||||
return &Nerf_Laser_Ops_Pro_Tag_Received_Buffers[2];
|
||||
}
|
||||
}
|
||||
|
||||
static inline void PackPulseTrain(TimedPulseTrain_T *pulsetrain, uint16_t data)
|
||||
{
|
||||
pulsetrain->bitstream[0] = NERF_LASER_OPS_PRO_HEADER_MARK;
|
||||
pulsetrain->bitstream[1] = NERF_LASER_OPS_PRO_HEADER_SPACE;
|
||||
pulsetrain->bitstream[2] = NERF_LASER_OPS_PRO_HEADER_MARK;
|
||||
pulsetrain->bitstream[3] = NERF_LASER_OPS_PRO_SPACE;
|
||||
|
||||
for (uint8_t n = 0; n < 16; n++)
|
||||
{
|
||||
if ((data & 0x01) == 0x01)
|
||||
{
|
||||
pulsetrain->bitstream[4 + (n * 2)] = NERF_LASER_OPS_PRO_ONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
pulsetrain->bitstream[4 + (n * 2)] = NERF_LASER_OPS_PRO_ZERO;
|
||||
}
|
||||
pulsetrain->bitstream[4 + (n * 2) + 1] = NERF_LASER_OPS_PRO_SPACE;
|
||||
data = data >> 1;
|
||||
}
|
||||
|
||||
pulsetrain->bitstream[35] = NERF_LASER_OPS_PRO_END;
|
||||
}
|
||||
|
||||
TimedPulseTrain_T *NERF_LASER_OPS_PRO_EncodePacket(TagPacket_T *packet)
|
||||
{
|
||||
uint16_t packed_data = 0;
|
||||
|
||||
if (packet->team_ID == NERF_RED_TEAM)
|
||||
{
|
||||
packed_data = RED_TEAM_PACKET_DATA;
|
||||
}
|
||||
else if (packet->team_ID == NERF_BLUE_TEAM)
|
||||
{
|
||||
packed_data = BLUE_TEAM_PACKET_DATA;
|
||||
}
|
||||
else // NERF_PURPLE_TEAM
|
||||
{
|
||||
packed_data = PURPLE_TEAM_PACKET_DATA;
|
||||
}
|
||||
|
||||
PackPulseTrain(&Tag_Send_Buffer, packed_data);
|
||||
|
||||
return &Tag_Send_Buffer;
|
||||
}
|
||||
|
||||
DecodedPacket_T *NERF_LASER_OPS_PRO_MaybeDecodePacket(TimedPulseTrain_T *packet)
|
||||
{
|
||||
// Some implementations (ESP32) do not report odd numbers of pulses.
|
||||
if ((packet->count != 35) && (packet->count != 36))
|
||||
{
|
||||
// Fail fast!
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Convert pulse durations to bits.
|
||||
// packet->bitstream[0] is the header mark--ignore it.
|
||||
// packet->bitstream[1] is the header space--ignore it also.
|
||||
// packet->bitstream[2] is the second header mark--ignore it as well.
|
||||
// packet->bitstream[3] is the second header space--also ignored.
|
||||
uint16_t data = 0;
|
||||
for (uint8_t n = 0; n < 16; n++)
|
||||
{
|
||||
// Even pulses are marks; odd pulses are spaces.
|
||||
if ((packet->bitstream[4 + (n * 2)].duration > MIN_MARK_ONE_IN_us) && (packet->bitstream[4 + (n * 2)].duration < MAX_MARK_ONE_IN_us))
|
||||
{
|
||||
// One
|
||||
data |= ((uint16_t)1 << n);
|
||||
}
|
||||
else if ((packet->bitstream[4 + (n * 2)].duration > MIN_MARK_ZERO_IN_us) && (packet->bitstream[4 + (n * 2)].duration < MAX_MARK_ZERO_IN_us))
|
||||
{
|
||||
// Zero--nothing to do.
|
||||
}
|
||||
else
|
||||
{
|
||||
// This mark is neither a zero or a one; abort.
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (data == RED_TEAM_PACKET_DATA)
|
||||
{
|
||||
DecodedPacket_T *Tag_Rx_Buffer = Get_Tag_Packet_Buffer();
|
||||
Tag_Rx_Buffer->Tag.type = DECODED_PACKET_TYPE_TAG_RECEIVED;
|
||||
Tag_Rx_Buffer->Tag.protocol = NERF_LASER_OPS_PRO_PROTOCOL;
|
||||
Tag_Rx_Buffer->Tag.player_ID = 0;
|
||||
Tag_Rx_Buffer->Tag.team_ID = NERF_RED_TEAM;
|
||||
Tag_Rx_Buffer->Tag.damage = 10;
|
||||
Tag_Rx_Buffer->Tag.color = COLOR_RED;
|
||||
return Tag_Rx_Buffer;
|
||||
}
|
||||
else if (data == BLUE_TEAM_PACKET_DATA)
|
||||
{
|
||||
DecodedPacket_T *Tag_Rx_Buffer = Get_Tag_Packet_Buffer();
|
||||
Tag_Rx_Buffer->Tag.type = DECODED_PACKET_TYPE_TAG_RECEIVED;
|
||||
Tag_Rx_Buffer->Tag.protocol = NERF_LASER_OPS_PRO_PROTOCOL;
|
||||
Tag_Rx_Buffer->Tag.player_ID = 0;
|
||||
Tag_Rx_Buffer->Tag.team_ID = NERF_BLUE_TEAM;
|
||||
Tag_Rx_Buffer->Tag.damage = 10;
|
||||
Tag_Rx_Buffer->Tag.color = COLOR_BLUE;
|
||||
return Tag_Rx_Buffer;
|
||||
}
|
||||
else if (data == PURPLE_TEAM_PACKET_DATA)
|
||||
{
|
||||
DecodedPacket_T *Tag_Rx_Buffer = Get_Tag_Packet_Buffer();
|
||||
Tag_Rx_Buffer->Tag.type = DECODED_PACKET_TYPE_TAG_RECEIVED;
|
||||
Tag_Rx_Buffer->Tag.protocol = NERF_LASER_OPS_PRO_PROTOCOL;
|
||||
Tag_Rx_Buffer->Tag.player_ID = 0;
|
||||
Tag_Rx_Buffer->Tag.team_ID = NERF_PURPLE_TEAM;
|
||||
Tag_Rx_Buffer->Tag.damage = 10;
|
||||
Tag_Rx_Buffer->Tag.color = COLOR_PURPLE;
|
||||
return Tag_Rx_Buffer;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
color_t NERF_LASER_OPS_PRO_GetTeamColor(uint8_t team_ID)
|
||||
{
|
||||
color_t result = COLOR_PURPLE;
|
||||
|
||||
if (team_ID == NERF_RED_TEAM)
|
||||
{
|
||||
result = COLOR_RED;
|
||||
}
|
||||
else if (team_ID == NERF_BLUE_TEAM)
|
||||
{
|
||||
result = COLOR_BLUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue