- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'm a relative noob to PSOC, and am trying to identify the simplest/best (leaning strongly toward simplest 🙂 approach to implementing a counter that can count up and down. The 'Base Counter' verilog component outwardly looks like it might fit the bill (specifically, it's 'Clock and Direction' mode), but I can find no data sheet, documentation, code examples, etc for it. (I've started picking my way through the .v file for it, but it's slow going for a noob.)
Is there any type of code example for the use of this component? If someone more experienced thinks this is not the simplest/best approach to implementing a counter that can count up and/or down, I'd be open to suggestions!
I'm trying to implement a step/dir stepper driver, and would ideally like to use the counter value to keep track the motor's assumed position, as it is subsequently fed pos/neg steps by a PID process, if that helps add any clarity to what I'm trying to get to. The other side of that is that I'd like it to sort of be a 'fire and forget' type of process - w/o the need for interrupts, continually calling the stepper routine, etc - so call a 'moveToPosition(p)' and/or 'moveSteps(s)' type of function, would set the counter's compare or period value, sets the direction needed to get there, and then the hardware drives the needed number of step pulses to get to the target position, w/o the firmware having to really be involved. (I'm also open to suggestions on that type of process, if anyone has any to offer!)
Oh, I'm working with a PSOC62 on the CY8CKIT-062-WiFi-BT Pioneer Kit.
Thanks for any assistance - I'm loving the PSOC world, it's just a whole 'nuther level beyond the simpler uC's I've used in the past! 🙂
Jim
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
Although I think that using Datapath should be more efficient, I tried using Verilog.
I used CY8CKIT-062-WiFi-BT.
========================
//`#start body` -- edit after this line, do not edit this line
module ud_cntr(
input rst, /* cync clear */
input clk, /* clock */
input up_ndn, /* 0: down 1: up */
input [7:0] max, /* max value */
output reg [7:0] cnt, /* count value */
output tc /* terminal count */
) ;
assign tc = (up_ndn == 1'b1) ? cnt == max : cnt == 8'd0 ;
always @(posedge clk) begin
if (rst == 1'b1)
if (up_ndn == 1'b1) /* up count */
cnt <= 8'd0 ;
else /* down count */
cnt <= max ;
else
if (up_ndn == 1'b1) /* up count */
if (cnt < max)
cnt <= cnt + 8'd1 ;
else
cnt <= 8'd0 ;
else /* down count */
if (cnt > 8'd0)
cnt <= cnt - 8'd1 ;
else
cnt <= max ;
end
endmodule
//`#end` -- edit above this line, do not edit this line
========================
To test the module, I utilized tty_utils.[ch] and func_list.[ch] from my sample code
MCU Tester, a Swiss Army Knife for PSoC (CY8CKIT-062-BLE version)
Tera Term log
Schematic
Pins
main_cm4.c
==================
#include "project.h"
#include "stdio.h"
#include "tty_utils.h"
#include "func_list.h"
int current_core = USE_CM4 ;
void do_help(void) ;
void do_step(void) ;
void do_run(void) ;
void do_up(void) ;
void do_down(void) ;
void do_max(void) ;
void do_reset(void) ;
void do_status(void) ;
void cycle_clock(void) ;
void show_values(void) ;
f_list_type main_func_list[] = {
{ "help", do_help, "show help message" },
{ "step", do_step, "advance 1 cycle" },
{ "run", do_run, "advance n cycles:<ex> run 4" },
{ "up" , do_up, "set direction to up count" },
{ "down", do_down, "set direction to down count" },
{ "max", do_max, "set max vaule" },
{ "reset", do_reset, "reset the counter" },
{ "status", do_status, "show current setup" },
{ 0, 0, 0 }
} ;
void init_hardware(void)
{
__enable_irq(); /* Enable global interrupts. */
tty_init(USE_CM4) ;
}
int main(void)
{
func_ptr func ;
init_hardware() ;
cls() ;
splash("PSoC 6 Verilog Counter Test") ;
do_help() ;
prompt("> ") ;
for(;;)
{
if (get_line()) {
func = get_func(main_func_list, str) ;
if (func) {
func() ;
} else {
print("Unknown Command: ") ;
print(str) ;
print("\r\n") ;
do_help() ;
}
prompt("> ") ;
}
}
}
void cycle_clock(void)
{
uint8_t tmp ;
tmp = Control_Reg_Read() ;
tmp = tmp ^ 0x02 ; /* clock = 0 */
Control_Reg_Write(tmp) ;
tmp = tmp | 0x02 ; /* clock = 1 */
Control_Reg_Write(tmp) ;
tmp = tmp ^ 0x02 ; /* clock = 0 */
Control_Reg_Write(tmp) ;
}
void show_values(void)
{
char buf[32] ;
snprintf(buf, 30, "%d %d\n\r", CNT_Read(), TC_Read()) ;
print(buf) ;
}
void do_help(void)
{
show_help(main_func_list) ;
}
void do_step(void)
{
cycle_clock() ;
show_values() ;
}
void do_run(void)
{
int i, n ;
sscanf(str, "%*s %d", &n) ;
for (i = 0 ; i < n ; i++ ) {
cycle_clock() ;
show_values() ;
CyDelay(10) ;
}
}
void do_up(void)
{
uint8_t tmp ;
tmp = Control_Reg_Read() ;
tmp |= 0x4 ; /* up_ndn = 1 */
Control_Reg_Write(tmp) ;
}
void do_down(void)
{
uint8_t tmp ;
tmp = Control_Reg_Read() ;
tmp ^= 0x4 ; /* up_ndn = 0 */
Control_Reg_Write(tmp) ;
}
void do_max(void)
{
int max ;
sscanf(str, "%*s %d", &max) ;
max_Write(max) ;
}
void do_reset(void)
{
uint8_t tmp ;
tmp = Control_Reg_Read() ;
tmp |= 0x01 ; /* reset = 1 */
Control_Reg_Write(tmp) ;
cycle_clock() ;
tmp ^= 0x01 ; /* reset = 0 */
Control_Reg_Write(tmp) ;
show_values() ;
}
void do_status(void)
{
uint8_t tmp, max, cnt, tc ;
tmp = Control_Reg_Read() ;
max = max_Read() ;
cnt = CNT_Read() ;
tc = TC_Read() ;
print("=== Current Status ===\n\r") ;
snprintf(str, STR_BUF_LEN, "Reset: %d\n\r", tmp & 0x01) ;
print(str) ;
snprintf(str, STR_BUF_LEN, "Clock: %d\n\r", (tmp >> 1) & 0x01) ;
print(str) ;
print("Direction: ") ;
if (tmp & 0x04) {
print("Up\n\r") ;
} else {
print("Down\n\r") ;
}
snprintf(str, STR_BUF_LEN, "Max: %d\n\r", max) ;
print(str) ;
snprintf(str, STR_BUF_LEN, "Count: %d\n\r", cnt) ;
print(str) ;
snprintf(str, STR_BUF_LEN, "Terminal Count: %d\n\r", tc) ;
print(str) ;
print("\n\r") ;
}
==================
moto