-
-
Notifications
You must be signed in to change notification settings - Fork 60
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
drv/counter_lpf2: Rework uartdev counter.
The purpose of this driver is to clean up the counter mixed in with uartdev, which was getting hard to follow. We will be using a single motor mode going forward. By dropping the hardcoded multi-mode setup and readout, we can treat motors like any other LPF2 sensor. This also removes user restrictions on setting the mode. This also reduces code size by about 250 bytes.
- Loading branch information
1 parent
9573fe3
commit ae927ac
Showing
23 changed files
with
357 additions
and
247 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
// SPDX-License-Identifier: MIT | ||
// Copyright (c) 2022 The Pybricks Authors | ||
|
||
// LPF2 Counter driver | ||
// | ||
// This driver parses type-specific position readouts from LPF2 motors. | ||
// | ||
// This driver currently requires that pbdrv_counter_lpf2_get_count gets | ||
// called often enough to observe full-rotation transitions of motors that | ||
// use absolute encoders. | ||
|
||
#include <pbdrv/config.h> | ||
|
||
#if PBDRV_CONFIG_COUNTER_LPF2 | ||
|
||
#include <stdint.h> | ||
|
||
#include <pbdrv/ioport.h> | ||
#include <pbio/error.h> | ||
#include <pbio/iodev.h> | ||
#include <pbio/util.h> | ||
|
||
#include "counter.h" | ||
#include "counter_lpf2.h" | ||
|
||
typedef struct { | ||
int32_t rotations; | ||
int32_t last_abs_pos; | ||
} private_data_t; | ||
|
||
#define PBDRV_COUNTER_UNKNOWN_ABS_ANGLE (INT32_MAX) | ||
|
||
static private_data_t private_data[PBDRV_CONFIG_COUNTER_LPF2_NUM_DEV]; | ||
|
||
static pbio_error_t pbdrv_counter_lpf2_get_count(pbdrv_counter_dev_t *dev, int32_t *count) { | ||
|
||
private_data_t *priv = dev->priv; | ||
const pbdrv_counter_lpf2_platform_data_t *pdata = dev->pdata; | ||
|
||
// Get iodev, and test if still connected. | ||
pbio_iodev_t *iodev; | ||
pbio_error_t err = pbdrv_ioport_get_iodev(pdata->port_id, &iodev); | ||
if (err != PBIO_SUCCESS) { | ||
return err; | ||
} | ||
|
||
// Ensure we are still dealing with a motor. | ||
if (!PBIO_IODEV_IS_FEEDBACK_MOTOR(iodev)) { | ||
return PBIO_ERROR_NO_DEV; | ||
} | ||
|
||
// Ensure that we are on expected mode. | ||
uint8_t mode_id = PBIO_IODEV_IS_ABS_MOTOR(iodev) ? | ||
PBIO_IODEV_MODE_PUP_ABS_MOTOR__APOS: | ||
PBIO_IODEV_MODE_PUP_REL_MOTOR__POS; | ||
if (iodev->mode != mode_id) { | ||
return PBIO_ERROR_INVALID_OP; | ||
} | ||
|
||
// Get LPF2 data buffer. | ||
uint8_t *data; | ||
pbio_iodev_get_data(iodev, &data); | ||
|
||
// For incremental encoders, we can just return the LPF2 data directly. | ||
if (!PBIO_IODEV_IS_ABS_MOTOR(iodev)) { | ||
*count = pbio_get_uint32_le(data); | ||
priv->last_abs_pos = PBDRV_COUNTER_UNKNOWN_ABS_ANGLE; | ||
return PBIO_SUCCESS; | ||
} | ||
|
||
// For absolute encoders, we need to keep track of whole rotations. | ||
int32_t abs_pos = (int16_t)pbio_get_uint16_le(data); | ||
|
||
// Update rotation counter as encoder passes through -180 | ||
if (abs_pos < -90 && priv->last_abs_pos > 90) { | ||
priv->rotations += 1; | ||
} | ||
if (abs_pos > 90 && priv->last_abs_pos < -90) { | ||
priv->rotations -= 1; | ||
} | ||
priv->last_abs_pos = abs_pos; | ||
|
||
// The total count is the position in this circle plus full rotations. | ||
*count = priv->rotations * 360 + abs_pos; | ||
return PBIO_SUCCESS; | ||
} | ||
|
||
static pbio_error_t pbdrv_counter_lpf2_get_abs_count(pbdrv_counter_dev_t *dev, int32_t *count) { | ||
private_data_t *priv = dev->priv; | ||
|
||
// Get total count value, which also updates absolute count value. | ||
pbio_error_t err = pbdrv_counter_lpf2_get_count(dev, count); | ||
if (err != PBIO_SUCCESS) { | ||
return err; | ||
} | ||
|
||
if (priv->last_abs_pos == PBDRV_COUNTER_UNKNOWN_ABS_ANGLE) { | ||
return PBIO_ERROR_NOT_SUPPORTED; | ||
} | ||
|
||
*count = priv->last_abs_pos; | ||
|
||
return PBIO_SUCCESS; | ||
} | ||
|
||
static const pbdrv_counter_funcs_t pbdrv_counter_lpf2_funcs = { | ||
.get_count = pbdrv_counter_lpf2_get_count, | ||
.get_abs_count = pbdrv_counter_lpf2_get_abs_count, | ||
}; | ||
|
||
void pbdrv_counter_lpf2_init(pbdrv_counter_dev_t *devs) { | ||
for (int i = 0; i < PBIO_ARRAY_SIZE(private_data); i++) { | ||
const pbdrv_counter_lpf2_platform_data_t *pdata = | ||
&pbdrv_counter_lpf2_platform_data[i]; | ||
private_data_t *priv = &private_data[i]; | ||
pbdrv_counter_dev_t *dev = &devs[pdata->counter_id]; | ||
|
||
dev->pdata = pdata; | ||
dev->funcs = &pbdrv_counter_lpf2_funcs; | ||
dev->priv = priv; | ||
} | ||
} | ||
|
||
#endif // PBDRV_CONFIG_COUNTER_LPF2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// SPDX-License-Identifier: MIT | ||
// Copyright (c) 2022 The Pybricks Authors | ||
|
||
#ifndef _INTERNAL_PVDRV_COUNTER_LPF2_H_ | ||
#define _INTERNAL_PVDRV_COUNTER_LPF2_H_ | ||
|
||
#include <pbdrv/config.h> | ||
|
||
#if PBDRV_CONFIG_COUNTER_LPF2 | ||
|
||
#if !PBDRV_CONFIG_COUNTER_LPF2_NUM_DEV | ||
#error Platform must define PBDRV_CONFIG_COUNTER_LPF2_NUM_DEV | ||
#endif | ||
|
||
#include <stdint.h> | ||
|
||
#include <pbdrv/counter.h> | ||
#include <pbio/port.h> | ||
|
||
typedef struct { | ||
/** The ID of the counter device provided by this instance. */ | ||
uint8_t counter_id; | ||
/** The I/O port identifier this counter is associated with. */ | ||
pbio_port_id_t port_id; | ||
} pbdrv_counter_lpf2_platform_data_t; | ||
|
||
// defined in platform/*/platform.c | ||
extern const pbdrv_counter_lpf2_platform_data_t | ||
pbdrv_counter_lpf2_platform_data[PBDRV_CONFIG_COUNTER_LPF2_NUM_DEV]; | ||
|
||
void pbdrv_counter_lpf2_init(pbdrv_counter_dev_t *devs); | ||
|
||
#else // PBDRV_CONFIG_COUNTER_LPF2 | ||
|
||
#define pbdrv_counter_lpf2_init(devs) | ||
|
||
#endif // PBDRV_CONFIG_COUNTER_LPF2 | ||
|
||
#endif // _INTERNAL_PVDRV_COUNTER_LPF2_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.