1# Copyright 2022 Cypress Semiconductor Corporation
2# SPDX-License-Identifier: Apache-2.0
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#     http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16# From https://wiki.tcl-lang.org/page/constants
17proc const {name value} {
18    uplevel 1 [list set $name $value]
19    uplevel 1 [list trace var $name w {error constant} ]
20}
21
22# Constant
23const REQ_PERI_CLOCK_ACCURACY 0.0025
24const EXPECTED_FREQ_MAX 100250
25const EXPECTED_FREQ_MIN 99750
26
27# Name of returned parameters
28const UPPER_DIV "upperDiv"
29const LOWER_DIV "lowerDiv"
30const BEST_DIV "bestDiv"
31const RESULT "result"
32
33# Result constant
34const THE_DIV_VALUE_IS_FOUND 0
35const THE_DIV_VALUE_IS_NOT_FOUND 1
36const RESULT_BAD_ACCURACY 2
37
38# Send data to personality
39proc output_results {upper_div lower_div best_div result} {
40    puts $::channelName "param:$::UPPER_DIV=$upper_div"
41    puts $::channelName "param:$::LOWER_DIV=$lower_div"
42    puts $::channelName "param:$::BEST_DIV=$best_div"
43    puts $::channelName "param:$::RESULT=$result"
44}
45
46# The number of input parameters
47const NUM_OF_ARG 2
48
49# Main function
50proc main {} {
51    if {$::argc != $::NUM_OF_ARG} {
52        error "Script requires two input parameters"
53        return 0
54    }
55
56    set peri_clock_freq [lindex $::argv 0]
57    set peri_clock_accuracy [lindex $::argv 1]
58
59    # Set default statuses
60    set upper_div 0
61    set lower_div 0
62    set best_div  0
63    set result $::THE_DIV_VALUE_IS_FOUND
64
65    # Check accuracy
66    if {$peri_clock_accuracy > $::REQ_PERI_CLOCK_ACCURACY} {
67        set result $::RESULT_BAD_ACCURACY
68    } else {
69
70        set upper_freq_limit_real [expr {$::EXPECTED_FREQ_MAX / (1 + $peri_clock_accuracy)}]
71        set lower_freq_limit_real [expr {$::EXPECTED_FREQ_MIN / (1 - $peri_clock_accuracy)}]
72
73        set upper_div [expr {floor($peri_clock_freq / $lower_freq_limit_real)}]
74        set lower_div [expr {ceil($peri_clock_freq / $upper_freq_limit_real)}]
75
76        if {$lower_div > $upper_div} {
77            set result $::THE_DIV_VALUE_IS_NOT_FOUND
78        } else {
79            set best_div [expr {$lower_div + round(($upper_div - $lower_div) / 2)}]
80        }
81    }
82
83    if {$result != $::THE_DIV_VALUE_IS_FOUND} {
84        set upper_div 0
85        set lower_div 0
86        set best_div  0
87    }
88
89    output_results $upper_div $lower_div $best_div $result
90}
91
92
93# Select output methods
94set channelName stdout
95if {[chan names ModusToolbox] eq "ModusToolbox"} {
96    set channelName ModusToolbox
97}
98
99# Start calculation
100main
101