|
Perl Weekly
Issue #135 - 2014-02-24 - What are you doing?
latest | archive | by Gabor Szabo
|
|
Hi,
Two new events added: one in Cluj, Romania and the other in Paris. See them at the end of the edition along with links to lots of other Perl-related events.
A few days ago, I started to build a new site called EduMaven, where I am going to publish slides of my courses. At first I think I am going to stick to the non-Perl courses. With your help, I'll get lots of new visitors, and then unleash the Perl slides on them. Does that sound like a good plan?
Anyway, enjoy the weekly dose of Perl articles:
|
|
|
|
Sponsors
|
We're Hiring Perl Software Developers - Grant Street Group
We're a growing software company using open source software/modern Perl practices to build innovative e-payment, auction, and tax collection web applications. We're looking for talented, motivated professionals committed to flawless work and customer service. Please apply online.
|
|
Articles
|
|
|
|
|
Testing
|
Test Suites: To Critic or Not?
Using Perl::Critic to improve the code of your module is important, but is it also important to use it to clean up your tests? Asks Randy J. Ray. (hint: yes)
|
|
Code
|
|
|
Web
|
|
|
|
|
CPAN
|
Make sure your modules have a compliant abstract
Neil Bowers continues his quest to make CPAN a better place. This time he calls upon the CPAN authors to make sure the one-line abstract they have for their modules is well formatted. (This is another excellent opportunity to get your feet wet if you'd like to contribute to a CPAN module. Help an author fix the tag-line.)
|
|
|
|
|
|
|
|
|
|
Fun
|
|
|
Grants
|
2013 Year end report
This is the annual report of The Perl Foundation. Many thanks to Dan Wright who started to produce these reports in the last 2 or 3 years.
|
|
Parrot
|
|
|
People
|
|
|
|
|
Perl 6
|
|
|
Other
|
|
|
Please Join Gittip
Gittip is a place where you can set up a regular weekly contribution to someone (probably an open source developer). Last week Peter Rabbitson called upon the Perl community to join Gittip and start giving a few dollars a week, this time it is Ovid. His point was that even just having Perl on the front page of Gittip will help Perl. Indeed his call brought Perl from the 19th place to the 10th place. I think we can do even better. The only thing you need to do is to join the 'Perl community' at Gittip. This is free. - Of course I'd go further and call upon you to start sending a few dollars a week.
|
|
|
|
Weekly collections
|
|
|
|
|
Perl Maven Tutorials
|
|
|
|
|
Events
|
Sponsoring Perl events by running Perl training courses
Perl events need funding. Developers need training. Companies need more knowledgeable developer. Some of us like teaching and visiting places. A win-win situation. So if you are an organizer, please get in touch, but if you are a would be attendee at one of the events, you could also contact the organizers and ask them about courses.
|
|
|
|
|
|
Perl-related events
In the following cities: Lyon (FR), Hannover (DE), Cluj (RO), Swindon (UK), Utrecht (NL), Silver Spring, (MD/USA), Poznan (PL), Prague (CZ), Oslo (NO), Paris (FR), Kiev (UA), Orlando (FL/US), Sofia (BG), Flörli Olten (CH)
|
|
You know, you could get the Perl Weekly right in your mailbox. Every Week. Free of charge!
|


帐号表
@collection
| Field | Type | Label | Description |
| ID | int64 | mongodb默认主键_id做账号id @bson=_id |
|
| UID | string | 客户端传来的唯一id,如微信unionID |
|
| RegisterTime | int64 | 密码 string Password = 4; 注册时间 |
|
| location | string | token校验 string accessToken = 6; string refreshToken = 7; 登陆地理位置 |
|
| password | string | 密码 |
|
| Ban | int32 | 帐号状态 1=游客, 2=注册, 3=绑定 E_AccountState State = 6; 密钥 string Token = 7; 上次服务器ID int32 LastLoginServerID = 8; 登录过服务器ID列表 repeated int32 LoginList = 9; 渠道名 string ChannelName = 10; 渠道帐号 string ChannelAccount = 11; 封号标记,1为被封 |
用户物品信息
| Field | Type | Label | Description |
| UID | string | 唯一id |
|
| TID | int32 | 类型id, item.xlsx中的id字段 |
|
| CreateTime | int64 | 创建时刻 |
|
| Num | int32 | 数量 |
用户货币信息
| Field | Type | Label | Description |
| Type | int32 | 类型, 1=金币,2=钻石,3积分 |
|
| Num | int64 | 数量 |
用户数据
@collection
| Field | Type | Label | Description |
| ID | int64 | mongodb默认主键_id做用户id @bson=_id |
|
| AccountID | int64 | 帐号id |
|
| Level | int32 | 等级 |
|
| AvatarURL | string | 头像url |
|
| NickName | string | 服务器ID int32 ServerID = 3; 名字 |
|
| Sex | string | 性别 |
|
| CreateTime | int64 | 创建时刻 |
|
| LastLoginTime | int64 | 上次登录时刻 |
|
| LastLogoutTime | int64 | 上次登出时刻 |
|
| Monies | Money | repeated | 货币信息 |
| Items | Item | repeated | 物品 |
| Exp | int64 | 经验 |
|
| DaySigned | bool | 今日是否已签到 |
|
| SignedDays | int32 | 已签到天数 |
|
| SignRewards | Item | repeated | 每日签到奖励,数组第几个代表第几天 任务状态 |
| .proto Type | Notes | C++ Type | Java Type | Python Type |
| double | double | double | float | |
| float | float | float | float | |
| int32 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead. | int32 | int | int |
| int64 | Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead. | int64 | long | int/long |
| uint32 | Uses variable-length encoding. | uint32 | int | int/long |
| uint64 | Uses variable-length encoding. | uint64 | long | int/long |
| sint32 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. | int32 | int | int |
| sint64 | Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. | int64 | long | int/long |
| fixed32 | Always four bytes. More efficient than uint32 if values are often greater than 2^28. | uint32 | int | int |
| fixed64 | Always eight bytes. More efficient than uint64 if values are often greater than 2^56. | uint64 | long | int/long |
| sfixed32 | Always four bytes. | int32 | int | int |
| sfixed64 | Always eight bytes. | int64 | long | int/long |
| bool | bool | boolean | boolean | |
| string | A string must always contain UTF-8 encoded or 7-bit ASCII text. | string | String | str/unicode |
| bytes | May contain any arbitrary sequence of bytes. | string | ByteString | str |


{% extends "_post.html" %}
{% hyde
title: "List Out of Lambda"
snip: "Down the rabbit hole we go!"
created: 2013-03-30 14:00:00
flattr: true
%}
{% block article %}
If you ignore the practical issues of computers like size, weight, cost, heat,
and so on, what do you *really* need in a programming language? Let's play
around with this question.
To understand this post you'll need a basic understanding of how functions in
Javascript work. If you can look at this code and understand what it prints,
you're good to go:
:::javascript
var x = 10;
var f = function(y) {
console.log(x);
console.log(y);
}
var g = f;
f(1);
g(2);
This blog post is a thought exercise. It's not something you'd ever use for
real code. But just like a guitarist practices scales that she won't ever play
in a song, we programmers should be exercising our brains every so often.
I'm going to use Javascript for the examples. Any language with first class
functions and lexical scoping (basically: closures) will work. The examples
would be prettier in a Lisp, but some people would be turned off by the syntax
and miss out on some interesting ideas. Feel free to port the code if it
bothers you.
If you've already seen this kind of thing before (maybe you've gone through [The
Little Schemer][] or [SICP][]) you may want to just skim the code here and look
for anything new.
If you *haven't* seen anything like this, then you're in for a treat! It's all
going to look extremely weird the first time you see it. Go slowly and make
sure you understand each piece fully before moving on to the next. These
concepts may be unintuitive, but they're built from very simple pieces.
Finally: if you get stuck, don't worry. Tracing out the execution of a function
on paper can be a good way to wrap your brain around it (I recommend investing
in a good lap desk for comfy reading and writing). If that doesn't work, just
close the window and come back tomorrow. Sometimes new concepts need a while to
rattle around in your brain before they click into place.
[The Little Schemer]: http://www.amazon.com/dp/0262560992/?tag=stelos-20
[SICP]: http://www.amazon.com/dp/0070004846/?tag=stelos-20
[TOC]
Lists
-----
Let's get started. One of the most common things we do as programmers is
grouping data together. Javascript has "arrays" built in to the language for
this:
:::javascript
var names = ["Alice", "Bob", "Candice"];
What if Javascript didn't come with arrays included? Could we create them (or
something like them) ourselves?
To answer this, let's think about the bare minimum we'd need to "bootstrap"
something like an array. There are a number of ways to do this, but we're going
to look at one in particular.
We'll call our array-like thing a "list". To make it work, we need four parts:
* The concept of "the empty list".
* A way to add an element to the front of a list.
* A way to take a list and get the first element.
* A way to take a list and get everything *but* the first element.
If we have those four things, we can build on top of them to do anything else we
might want. For example: to make a list of one item, you add that item to the
front of the empty list.
Let's narrow this down further. There are lots of ways you could implement
those four things -- I'm going to use functions. Let's sketch out an outline:
:::javascript
var empty_list = null;
var prepend = function(el, list) {
// ...
};
var head = function(list) {
// ...
};
var tail = function(list) {
// ...
};
var is_empty = function(list) {
// ...
};
Here are the descriptions of each of these items.
The `empty_list` is a special value that represents a list of zero elements.
It can be anything, so for now we'll use `null` (we'll revisit this later).
`prepend(1, some_list)` will return a new list that looks like the old one, but
with `1` stuck onto the front of it. So if we want to create a list of the
numbers `1` and `2` we can say `prepend(1, prepend(2, empty_list))` or "prepend
one to the result of prepending 2 to the empty list".
`head(some_list)` will return the first element in the list. Calling it on the
empty list will be undefined, so we'll just be very careful not to do that!
`tail(some_list)` will return a new list that's like the one we gave it, but
with the first element removed. Again, calling this on an empty list will make
things explode.
`is_empty(some_list)` will return `true` if the list given to it is the empty
list, and `false` otherwise.
Once we have those four functions (plus the special empty list value) we can
start building on top of them, so let's figure out how to make them!
### List Out of If
If you haven't seen anything like this before, you might think it's time to
start creating Javascript Objects. That's certainly one way to do it.
Since this post is a thought experiment in what we actually *need*, though,
let's try to avoid using big language features (like Objects) unless we
absolutely can't avoid it.
So if we don't want to use other language features yet, what are we left with?
Well so far our skeleton only has functions (and `null`), so let's try those!
Here's the first working revision of the building blocks of lists:
:::javascript
var empty_list = null;
var prepend = function(el, list) {
return function(command) {
if (command === "head") {
return el;
} else if (command === "tail") {
return list;
}
}
};
var head = function(list) {
return list("head");
};
var tail = function(list) {
return list("tail");
};
var is_empty = function(list) {
return list === null;
};
Go ahead and paste that into a browser console and play with it:
:::javascript
var e = empty_list;
console.log(is_empty(e));
// true
var names = prepend("Alice",
prepend("Bob",
prepend("Candice",
empty_list)));
console.log(is_empty(names));
// False
console.log(head(names));
// Alice
console.log(tail(names));
// Some function representing the list of ("Bob", "Candice")
console.log(head(tail(names)));
// Bob
### But Where is the Data?
Did the definitions of those functions surprise you? Lists seem like such an
important, object-oriented concept, but there only appear to be functions here!
Let's look at how this actually works. First of all, the "empty list" concept
is pretty straightforward:
:::javascript
var empty_list = null;
var is_empty = function(list) {
return list === null;
};
We could have picked any arbitrary value here. `null` seemed appropriate, so
I used that.
Now on to the meat of things: `prepend`.
:::javascript
var prepend = function(el, list) {
return function(command) {
if (command === "head") {
return el;
} else if (command === "tail") {
return list;
}
}
};
This is where the real magic happens. Let's think through it.
First of all, we know that when you prepend something to a list, you're going to
get a (new) list back. So whatever `prepend` returns must be a list.
Looking at the code, we can see it returns a function. So in our little thought
experiment, a list is actually a Javascript function under the hood!
So what do we need to do with lists (aside from empty checking, which we've
already covered)? Well, we need to be able to get the head and the tail. When
we call `prepend(h, t)`, we happen to be conveniently specifying the head and
tail as the arguments! So in `prepend` we return a function that knows how to
return its own head or tail when asked.
So a "list" is "a function that knows how to return its own head or tail when
asked". So our `head` and `tail` functions just need to ask nicely!
:::javascript
var head = function(list) {
return list("head");
};
var tail = function(list) {
return list("tail");
};
That's it! We've created lists in 23 lines of code without using any fancy
things like Objects. Before you move on, make sure you really understand why
this works. Write out a few examples on paper.
:::javascript
var empty_list = null;
var prepend = function(el, list) {
return function(command) {
if (command === "head") {
return el;
} else if (command === "tail") {
return list;
}
}
};
var head = function(list) {
return list("head");
};
var tail = function(list) {
return list("tail");
};
var is_empty = function(list) {
return list === null;
};
### Building on the Foundations
Now that we have lists, let's implement a few common things on top of them as
practice.
#### map
A common thing to do to a list is to create a new list by looping through it and
doing something to each item. This is called "map":
:::javascript
var map = function(fn, l) {
if (is_empty(l)) {
return empty_list;
} else {
return prepend(fn(head(l)), map(fn, tail(l)));
}
};
If you're not used to recursive definitions like this, you may way to take
a few minutes and try to work out how it works. Here's an example:
:::javascript
var square = function(x) {
return x * x;
}
var numbers = prepend(1, prepend(2, prepend(3, empty_list)));
var squared_numbers = map(square, numbers);
// map(square, [1, 2, 3])
// prepend(square(1), map(square, [1, 2, 3]))
// prepend(square(1), prepend(square(2), map(square, [3])))
// prepend(square(1), prepend(square(2), prepend(square(3), map(square, []))))
// prepend(square(1), prepend(square(2), prepend(square(3), [])))
// prepend(square(1), prepend(square(2), prepend(9, [])))
// prepend(square(1), prepend(square(2), [9]))
// prepend(square(1), prepend(4, [9]))
// prepend(square(1), [4, 9])
// prepend(1, [4, 9])
// [1, 4, 9]
I'm using brackets here to represent lists, but remember that these aren't
arrays, but are actually the functions that were returned by `prepend`.
If you're still not sure about this, trace out every step of `map(square,
empty_list)` on paper. Then trace out every step of `map(square, prepend(10,
empty_list))`.
Thinking recursively like this takes some practice. I have notebooks filled
with [pages like this](http://i.imgur.com/kqu5jy9.jpg). Experienced guitarists
practice new material slowly and methodically -- there's no reason programmers
shouldn't do the same. Watching the function calls expand and contract on paper
can help you feel in your gut how these things work in a way that just staring
at the words can't.
#### filter
We're going to start moving a bit faster now, but you should still make sure you
understand everything completely before moving on. Take as much time as you
need. Write things out. Run them. Get a feel for them.
The next "utility" function we'll build on top of lists is `filter`, which
takes a function and a list, and returns a new list whose elements are those in
the original that make the function return `true`. Here's an example:
:::javascript
var numbers = prepend(1, prepend(2, prepend(3, empty_list)));
var is_odd = function(x) {
return x % 2 === 1;
}
filter(is_odd, numbers);
// [1, 3]
Now let's implement `filter`:
:::javascript
var filter = function(fn, l) {
if (is_empty(l)) {
return empty_list;
} else if (fn(head(l))) {
return prepend(head(l), filter(fn, tail(l)));
} else {
return filter(fn, tail(l));
}
};
Take your time. Trace out some examples. Move on when you feel it in your gut.
#### and, or, not
Let's take a slight detour to implement a few "helper" functions. Τhese don't
have anything specifically to do with lists, but we'll need them later.
:::javascript
var not = function(x) {
if (x) {
return false;
} else {
return true;
}
};
var and = function(a, b) {
if (a) {
if (b) {
return true;
} else {
return false;
}
} else {
return false;
}
};
var or = function(a, b) {
if (a) {
return true;
} else {
if (b) {
return true;
} else {
return false;
}
}
};
Javascript already has these things built in as `!`, `&&`, and `||`, of course,
but remember that in this thought exercise we're trying to avoid using extra
language features if we don't need them. How far can we scrape by on just
functions and `if` statements?
One small note: these functions are just normal Javascript functions, which
means that `and(a, b)` will *not* short-circuit like `a && b` would. For our
purposes here that won't hurt us, but it's something to be aware of.
### List Out of Lambda
Now that we've had a bit more practice, let's go back to our definition of
lists:
:::javascript
var empty_list = null;
var prepend = function(el, list) {
return function(command) {
if (command === "head") {
return el;
} else if (command === "tail") {
return list;
}
}
};
var head = function(list) {
return list("head");
};
var tail = function(list) {
return list("tail");
};
var is_empty = function(list) {
return list === null;
};
There are a few things about this implementation that bother me. Our goal is to
use as few language features as possible, but we've actually used quite a few!
I count at least five:
* Functions
* `if` statements
* Strings
* Booleans (the `true`/`false` result of `is_empty`)
* Equality checking (the `===` checks)
It turns out we can remove most of those things at the cost of a bit of
readability (and more bending of our minds).
Let's start by rewriting the core three functions to ditch those ugly strings,
equality checks, and even the `if` statement:
:::javascript
var prepend = function(el, list) {
return function(selector) {
return selector(el, list);
};
};
var head = function(list) {
return list(function(h, t) {
return h;
});
};
var tail = function(list) {
return list(function(h, t) {
return t;
});
};
You may want to get a snack before wrapping your brain around this one! There's
no strings, no equality checking, no `if` statements. But we still have lists!
The `prepend` functions still returns a function, just like before. Remember
that in the last implementation, a "list" was really a function that knew how to
give out its head or its tail when asked for them.
This time, we're inverting the "asking". In this version, a "list" is "a
function that will tell another function about both its head *and* its tail when
asked". This time the *asker* gets *both* pieces, and can decide which one they
want to use.
Let's look at the `head` function:
* `head` takes a list and says `return list(...)`, which means: "Hey list,
I would like you to tell all of your info to this little helper function I'm
giving you".
* The list says `return ...(el, list)`, which means: "Okay helper function,
here's my head and my tail, enjoy!"
* The helper function that `head` originally gave was `function(h, t) { return
h; }`. So when the list calls it with the head and the tail as arguments, it
returns the head and ignores the tail.
* `head` takes that result and just returns it straight through back to the
caller.
`tail` works exactly the same way, but its helper function returns the second
argument (the tail) instead of the first.
That's it! The equality checking and `if` statements have disappeared. Can you
describe where they've gone? What has taken their place?
Before we move on, let's clean up the idea of the empty list. It's still using
`null` and equality checking. Let's remove those and make things a little more
uniform.
To do this we'll need to change the other three functions a bit as well, but if
you've understood everything so far it shouldn't be too bad.
:::javascript
var empty_list = function(selector) {
return selector(undefined, undefined, true);
};
var prepend = function(el, list) {
return function(selector) {
return selector(el, list, false);
};
};
var head = function(list) {
return list(function(h, t, e) {
return h;
});
};
var tail = function(list) {
return list(function(h, t, e) {
return t;
});
};
var is_empty = function(list) {
return list(function(h, t, e) {
return e;
});
};
We've now made lists a bit smarter. In addition to telling the helper function
their head and tail, they also tell it "am I the empty list?". We've modified
the helpers `head` and `tail` to accept (and ignore) this extra argument.
We then modified `is_empty` to work just like `head` and `tail`.
Finally, we've redefined `empty_list` to match the rest of the lists instead of
being a special, magic value. The empty list is now just like a normal one:
it's a function that takes an "asker" and tells that asker "Hey, my head and
tail are undefined and I am the empty list".
I used `undefined` here which is technically another language feature because
it's easier to read. Feel free to replace it with anything you want to make it
more pure. Since we're being very careful to never call `head` or `tail` on the
empty list those values will never be seen anyway.
So after all that, we've finally implemented the building blocks of lists with
only two things:
* Functions.
* `true` and `false` for empty lists.
If you're up for a challenge, think about whether you could remove that second
item (and if so, are you *really* removing it, or just using certain features of
Javascript implicitly instead of explicitly?).
A Brief Intermission
--------------------
Let's take a minute to reflect on all the code we've seen so far. First, we
have an implementation of lists that uses only functions and booleans:
:::javascript
var empty_list = function(selector) {
return selector(undefined, undefined, true);
};
var prepend = function(el, list) {
return function(selector) {
return selector(el, list, false);
};
};
var head = function(list) {
return list(function(h, t, e) {
return h;
});
};
var tail = function(list) {
return list(function(h, t, e) {
return t;
});
};
var is_empty = function(list) {
return list(function(h, t, e) {
return e;
});
};
From this point on, we can now ignore the details of how lists are implemented.
As long as we have `head`, `tail`, and `prepend` we don't need to worry about
what lists actually *are* under the hood.
We also built a few helper functions on top of this foundation:
:::javascript
var not = function(x) {
if (x) {
return false;
} else {
return true;
}
};
var and = function(a, b) {
if (a) {
if (b) {
return true;
} else {
return false;
}
} else {
return false;
}
};
var or = function(a, b) {
if (a) {
return true;
} else {
if (b) {
return true;
} else {
return false;
}
}
};
var map = function(fn, l) {
if (is_empty(l)) {
return empty_list;
} else {
return prepend(fn(head(l)), map(fn, tail(l)));
}
};
var filter = function(fn, l) {
if (is_empty(l)) {
return empty_list;
} else if (fn(head(l))) {
return prepend(head(l), filter(fn, tail(l)));
} else {
return filter(fn, tail(l));
}
};
Before you move on, make sure all of this code is crystal clear. Come back
tomorrow if you need to let it sink in. We're about to go a lot deeper into the
rabbit hole, so make sure you're ready.
Numbers
-------
If you look at the definitions of `prepend`, `head`, and `tail`, they're pretty
mind-bending. However, the definitions of `map` and `filter` are much more
straightforward.
This is because we encapsulated the implementation of lists into the first four
functions. We did all the hard work of building lists out of almost nothing at
all and hid it behind that simple `prepend`, `head`, and `tail` interface.
The idea of creating things from simple pieces and abstracting them into "black
boxes" is one of the most important parts of both computer science and
programming, so let's take it a step further and get some more practice by
implementing numbers.
### What is a Number?
For this blog post we're only going to concern ourselves with non-negative
integers. Feel free to try extending all this to include negative integers if
you want more.
How can we represent a number? Well we could obviously use Javascript numbers
like `14`, but that's not very fun, and we're trying to minimize the number of
language features we use.
One way to represent a number is a list whose length is the number. So we could
say that `[1, 1, 1]` means "three", `["cats", null]` means "two", and `[]` means
"zero".
The elements themselves don't really matter, so let's just pick something we
already have: the empty list! Let's write out a few to get a feel for this:
:::javascript
var zero = empty_list;
// []
var one = prepend(empty_list, empty_list);
// [ [] ]
var two = prepend(empty_list, prepend(empty_list, empty_list));
// [ [], [] ]
### inc, dec
We're going to want to *do* things with our numbers, so let's start writing
things that work with this "list of things" representation of numbers.
Our basic building blocks are going to be `inc` and `dec` (increment and
decrement).
:::javascript
var inc = function(n) {
return prepend(empty_list, n);
};
var dec = function(n) {
return tail(n);
};
To add 1 to a number, we just push another element on the list. So
`inc(inc(zero))` means "two".
To subtract 1, we just pop off one of the elements: `dec(two)` means "one"
(remember we're ignoring negative numbers).
### is\_zero
When we started working with lists we used `is_empty` a lot, so it's probably
a good idea to create an `is_zero` function at this point:
:::javascript
var is_zero = function(n) {
return is_empty(n);
};
Zero is just represented by the empty list, so this one is easy!
### add
Adding one is easy, but we're probably going to want to add arbitrary numbers
together. Now that we have `inc` and `dec` this is actually pretty easy:
:::javascript
var add = function(a, b) {
if (is_zero(b)) {
return a;
} else {
return add(inc(a), dec(b));
}
};
This is another recursive definition. When adding two numbers, there are two
possibilities:
* If `b` is zero, then anything plus zero is zero, so we can just return `a`.
* Otherwise, adding `a + b` is the same as adding `(a + 1) + (b - 1)`.
Eventually `b` will "bottom out" and return `a` (which has been steadily getting
bigger as `b` got smaller).
Notice how we didn't say anything about lists here! The "numbers are lists
under the hood" idea has been encapsulated behind `is_zero`, `inc`, and `dec`,
so we can ignore it and work at the "number" level of abstraction from here on
out.
### sub
Subtraction is similar to addition, but instead of *increasing* `a` as `b` gets
smaller, we *decrease* them both together:
:::javascript
var sub = function(a, b) {
if (is_zero(b)) {
return a;
} else {
return sub(dec(a), dec(b));
}
};
Now we can say something like `add(two, sub(three, two))` and the result will be
a representation of "three" in our system (which, of course, is a list of three
elements).
Pause for a minute now and remember that underneath numbers are lists, and
underneath lists there's nothing but functions. We can add and subtract
integers and underneath it all it's just functions shuffling around, expanding
into other functions and contracting as they're called, and this writhing mass
of lambdas somehow ends up representing `1 + 1 = 2`. That's pretty cool!
### mul, pow
For practice let's create a way to multiply numbers:
:::javascript
var mul = function(a, b) {
if (is_zero(b)) {
return zero;
} else {
return add(a, mul(a, dec(b)));
}
};
Building on `add` makes this pretty easy. `3 * 4` is the same as `3
+ 3 + 3 + 3 + 0`. Trace out the execution on paper if things are starting to
get away from you. Carry on when you're ready.
`pow` ("power" or exponential) follows a similar structure as `mul`, but instead
of adding together the copies we multiply them, and our base is one instead of
zero:
:::javascript
var pow = function(a, b) {
if (is_zero(b)) {
return one;
} else {
return mul(a, pow(a, dec(b)));
}
};
### is\_equal
A common thing to do with numbers is to check if two are equal, so let's write
that:
:::javascript
var is_equal = function(n, m) {
if (and(is_zero(n), is_zero(m))) {
return true;
} else if (or(is_zero(n), is_zero(m))) {
return false;
} else {
return is_equal(dec(n), dec(m));
}
};
There are three cases here:
* If both numbers are zero, they are equal.
* If only one number is zero (but not both, or the first case would have caught
it), then they are *not* equal.
* Otherwise, subtract one from each and try again.
When calling this function with two non-zero numbers, both will be decremented
in tandem until one of them bottoms out at zero first, or until they bottom out
at the same time.
### less\_than, greater\_than
We can take a similar approach to implementing `less_than`:
:::javascript
var less_than = function(a, b) {
if (and(is_zero(a), is_zero(b))) {
return false;
} else if (is_zero(a)) {
return true;
} else if (is_zero(b)) {
return false;
} else {
return less_than(dec(a), dec(b));
}
};
The difference here is that we have four cases.
* If both numbers are zero, then `a` is not less than `b`.
* Otherwise if `a` is zero (and we know `b` isn't) then yes, `a` is less than
`b`.
* Otherwise if `b` is zero (and we know that `a` isn't) then no, `a` cannot be
less than `b` (remember that we're ignoring negative numbers).
* Otherwise decrement both and try again.
Once again, both numbers race to bottom out, and the outcome is decided by which
one bottoms out first.
We could do something similar for `greater_than`, but let's do it the easy way
instead:
:::javascript
var greater_than = function(a, b) {
return less_than(b, a);
};
### div, mod
Once we have `less_than` we're ready to implement division and remainders:
:::javascript
var div = function(a, b) {
if (less_than(a, b)) {
return zero;
} else {
return inc(div(sub(a, b), b));
}
};
var rem = function(a, b) {
if (less_than(a, b)) {
return a;
} else {
return rem(sub(a, b), b);
}
};
This pair is a bit more complicated than the three other basic operations
because we can't deal with negative numbers. Make sure you understand how it
works.
Full Circle
-----------
At this point, we have a (very basic) working system of numbers built on top of
lists. Let's chase our tails a bit and implement a few more list functions that
use numbers.
### nth
To get the Nth item in a list, we just pop things off of it as we decrement
N until we hit zero:
:::javascript
var nth = function(l, n) {
if (is_zero(n)) {
return head(l);
} else {
return nth(tail(l), dec(n));
}
};
Under the hood there are really *two* lists getting things popped off as we
iterate, because `n` is a number, which is a list, and `dec` pops things off.
But it's much easier to read when we've abstracted away the representation of
numbers, don't you think?
### drop, take
Two handy functions for working with lists are `drop` and `take`.
`drop(l, three)` will return the list with the first three elements removed.
`take(l, three)` will return the list containing only the first three elements.
:::javascript
var drop = function(l, n) {
if (is_zero(n)) {
return l;
} else {
return drop(tail(l), dec(n));
}
};
var take = function(l, n) {
if (is_zero(n)) {
return empty_list;
} else {
return prepend(head(l), take(tail(l), dec(n)));
}
};
### slice
Slicing a list is easy now that we have `drop`, `take`, and the ability to
subtract numbers:
:::javascript
var slice = function(l, start, end) {
return take(drop(l, start), sub(end, start));
};
First we drop up to the start, then take enough to get us to the end.
### length
We can define `length` recursively like everything else:
:::javascript
var length = function(l) {
if (is_empty(l)) {
return zero;
} else {
return inc(length(tail(l)));
}
};
The length of the empty list is zero, and the length of any non-empty list is
one plus the length of its tail.
If your mind isn't in knots by this point, consider the following:
* Lists are made of functions.
* Numbers are made of lists whose length represents the number.
* `length` is a function that takes a list (which is a function) and returns
the length as a number (a list whose length represents the number).
* We only just now got around to defining `length` even though we've been using
numbers (which use the *length* of a list to represent a number) for a while
now!
Are you dizzy yet? If not:
:::javascript
var mylist = prepend(empty_list,
prepend(empty_list,
empty_list));
var mylistlength = length(mylist);
`mylist` is a list of two empty lists.
`mylistlength` is the length of `mylist`...
which is "two"...
which is represented by a list of two empty lists...
which is `mylist` itself!
Conclusion
----------
If you liked this twisty little story, I highly recommend you check out [The
Little Schemer][]. It was one of the first books that really changed how
I thought about programming. Don't be put off by the fact that it uses Scheme
-- the language doesn't really matter.
I've also created [a gist][] with all the code. Feel free to fork it and use it
for practice.
You could add some more utility functions for practice writing recursively:
* `append` to add an item to the end of a list.
* `concat` to concatenate two lists.
* `min` and `max` which take two numbers and return the minimum/maximum one.
* `remove`, which is like filter except it only leaves the elements that return
`false` for the predicate.
* `contains_number`, which checks if a specific number is inside a list of
numbers.
Or if you want something more challenging, try implementing bigger concepts on
top of the current ones:
* Negative numbers.
* Non-negative rational numbers.
* Negative rational numbers.
* Association lists (a data structure that associates keys with values).
Remember: the point is not to create something that runs well on a physical
computer. Instead of thinking about how to make a particular combination of
transistors and circuits have the right voltages, think about "computing" in the
beautiful, perfect, abstract sense.
[a gist]: https://gist.github.com/sjl/5277681
{% endblock article %}


|
M4521 BSP V3.01.000
The Board Support Package for M4521
|
Macros | |
| #define | EADC_CONV_RESET(eadc) ((eadc)->CTL |= EADC_CTL_ADRST_Msk) |
| A/D Converter Control Circuits Reset. More... | |
| #define | EADC_ENABLE_PDMA(eadc) ((eadc)->CTL |= EADC_CTL_PDMAEN_Msk) |
| Enable PDMA transfer. More... | |
| #define | EADC_DISABLE_PDMA(eadc) ((eadc)->CTL &= (~EADC_CTL_PDMAEN_Msk)) |
| Disable PDMA transfer. More... | |
| #define | EADC_ENABLE_DOUBLE_BUFFER(eadc, u32ModuleNum) ((eadc)->SCTL[(u32ModuleNum)] |= EADC_SCTL_DBMEN_Msk) |
| Enable double buffer mode. More... | |
| #define | EADC_DISABLE_DOUBLE_BUFFER(eadc, u32ModuleNum) ((eadc)->SCTL[(u32ModuleNum)] &= ~EADC_SCTL_DBMEN_Msk) |
| Disable double buffer mode. More... | |
| #define | EADC_ENABLE_INT_POSITION(eadc, u32ModuleNum) ((eadc)->SCTL[(u32ModuleNum)] |= EADC_SCTL_INTPOS_Msk) |
| Set ADIFn at A/D end of conversion. More... | |
| #define | EADC_DISABLE_INT_POSITION(eadc, u32ModuleNum) ((eadc)->SCTL[(u32ModuleNum)] &= ~EADC_SCTL_INTPOS_Msk) |
| Set ADIFn at A/D start of conversion. More... | |
| #define | EADC_ENABLE_INT(eadc, u32Mask) ((eadc)->CTL |= ((u32Mask) << EADC_CTL_ADCIEN0_Pos)) |
| Enable the interrupt. More... | |
| #define | EADC_DISABLE_INT(eadc, u32Mask) ((eadc)->CTL &= ~((u32Mask) << EADC_CTL_ADCIEN0_Pos)) |
| Disable the interrupt. More... | |
| #define | EADC_ENABLE_SAMPLE_MODULE_INT(eadc, u32IntSel, u32ModuleMask) ((eadc)->INTSRC[(u32IntSel)] |= (u32ModuleMask)) |
| Enable the sample module interrupt. More... | |
| #define | EADC_DISABLE_SAMPLE_MODULE_INT(eadc, u32IntSel, u32ModuleMask) ((eadc)->INTSRC[(u32IntSel)] &= ~(u32ModuleMask)) |
| Disable the sample module interrupt. More... | |
| #define | EADC_SET_DMOF(eadc, u32Format) ((eadc)->CTL = ((eadc)->CTL & ~EADC_CTL_DMOF_Msk) | (u32Format)) |
| Set the input mode output format. More... | |
| #define | EADC_START_CONV(eadc, u32ModuleMask) ((eadc)->SWTRG = (u32ModuleMask)) |
| Start the A/D conversion. More... | |
| #define | EADC_STOP_CONV(eadc, u32ModuleMask) ((eadc)->PENDSTS = (u32ModuleMask)) |
| Cancel the conversion for sample module. More... | |
| #define | EADC_GET_PENDING_CONV(eadc) ((eadc)->PENDSTS) |
| Get the conversion pending flag. More... | |
| #define | EADC_GET_CONV_DATA(eadc, u32ModuleNum) ((eadc)->DAT[(u32ModuleNum)] & EADC_DAT_RESULT_Msk) |
| Get the conversion data of the user-specified sample module. More... | |
| #define | EADC_GET_DATA_OVERRUN_FLAG(eadc, u32ModuleMask) ((((eadc)->STATUS0 >> EADC_STATUS0_OV_Pos) | ((eadc)->STATUS1 & EADC_STATUS1_OV_Msk)) & (u32ModuleMask)) |
| Get the data overrun flag of the user-specified sample module. More... | |
| #define | EADC_GET_DATA_VALID_FLAG(eadc, u32ModuleMask) ((((eadc)->STATUS0 & EADC_STATUS0_VALID_Msk) | (((eadc)->STATUS1 & EADC_STATUS1_VALID_Msk) << 16)) & (u32ModuleMask)) |
| Get the data valid flag of the user-specified sample module. More... | |
| #define | EADC_GET_DOUBLE_DATA(eadc, u32ModuleNum) ((eadc)->DDAT[(u32ModuleNum)] & EADC_DDAT_RESULT_Msk) |
| Get the double data of the user-specified sample module. More... | |
| #define | EADC_GET_INT_FLAG(eadc, u32Mask) ((eadc)->STATUS2 & (u32Mask)) |
| Get the user-specified interrupt flags. More... | |
| #define | EADC_GET_SAMPLE_MODULE_OV_FLAG(eadc, u32ModuleMask) ((eadc)->OVSTS & (u32ModuleMask)) |
| Get the user-specified sample module overrun flags. More... | |
| #define | EADC_CLR_INT_FLAG(eadc, u32Mask) ((eadc)->STATUS2 = (u32Mask)) |
| Clear the selected interrupt status bits. More... | |
| #define | EADC_CLR_SAMPLE_MODULE_OV_FLAG(eadc, u32ModuleMask) ((eadc)->OVSTS = (u32ModuleMask)) |
| Clear the selected sample module overrun status bits. More... | |
| #define | EADC_IS_DATA_OV(eadc) (((eadc)->STATUS2 & EADC_STATUS2_AOV_Msk) >> EADC_STATUS2_AOV_Pos) |
| Check all sample module A/D result data register overrun flags. More... | |
| #define | EADC_IS_DATA_VALID(eadc) (((eadc)->STATUS2 & EADC_STATUS2_AVALID_Msk) >> EADC_STATUS2_AVALID_Pos) |
| Check all sample module A/D result data register valid flags. More... | |
| #define | EADC_IS_SAMPLE_MODULE_OV(eadc) (((eadc)->STATUS2 & EADC_STATUS2_STOVF_Msk) >> EADC_STATUS2_STOVF_Pos) |
| Check all A/D sample module start of conversion overrun flags. More... | |
| #define | EADC_IS_INT_FLAG_OV(eadc) (((eadc)->STATUS2 & EADC_STATUS2_ADOVIF_Msk) >> EADC_STATUS2_ADOVIF_Pos) |
| Check all A/D interrupt flag overrun bits. More... | |
| #define | EADC_IS_BUSY(eadc) (((eadc)->STATUS2 & EADC_STATUS2_BUSY_Msk) >> EADC_STATUS2_BUSY_Pos) |
| Get the busy state of EADC. More... | |
| #define | EADC_ENABLE_CMP0(eadc, u32ModuleNum, u32Condition, u16CMPData, u32MatchCount) |
| Configure the comparator 0 and enable it. More... | |
| #define | EADC_ENABLE_CMP1(eadc, u32ModuleNum, u32Condition, u16CMPData, u32MatchCount) |
| Configure the comparator 1 and enable it. More... | |
| #define | EADC_ENABLE_CMP2(eadc, u32ModuleNum, u32Condition, u16CMPData, u32MatchCount) |
| Configure the comparator 2 and enable it. More... | |
| #define | EADC_ENABLE_CMP3(eadc, u32ModuleNum, u32Condition, u16CMPData, u32MatchCount) |
| Configure the comparator 3 and enable it. More... | |
| #define | EADC_ENABLE_CMP_WINDOW_MODE(eadc, u32CMP) ((eadc)->CMP[(u32CMP)] |= EADC_CMP_CMPWEN_Msk) |
| Enable the compare window mode. More... | |
| #define | EADC_DISABLE_CMP_WINDOW_MODE(eadc, u32CMP) ((eadc)->CMP[(u32CMP)] &= ~EADC_CMP_CMPWEN_Msk) |
| Disable the compare window mode. More... | |
| #define | EADC_ENABLE_CMP_INT(eadc, u32CMP) ((eadc)->CMP[(u32CMP)] |= EADC_CMP_ADCMPIE_Msk) |
| Enable the compare interrupt. More... | |
| #define | EADC_DISABLE_CMP_INT(eadc, u32CMP) ((eadc)->CMP[(u32CMP)] &= ~EADC_CMP_ADCMPIE_Msk) |
| Disable the compare interrupt. More... | |
| #define | EADC_DISABLE_CMP0(eadc) ((eadc)->CMP[0] = 0) |
| Disable comparator 0. More... | |
| #define | EADC_DISABLE_CMP1(eadc) ((eadc)->CMP[1] = 0) |
| Disable comparator 1. More... | |
| #define | EADC_DISABLE_CMP2(eadc) ((eadc)->CMP[2] = 0) |
| Disable comparator 2. More... | |
| #define | EADC_DISABLE_CMP3(eadc) ((eadc)->CMP[3] = 0) |
| Disable comparator 3. More... | |
Functions | |
| void | EADC_Open (EADC_T *eadc, uint32_t u32InputMode) |
| This function make EADC_module be ready to convert. More... | |
| void | EADC_Close (EADC_T *eadc) |
| Disable EADC_module. More... | |
| void | EADC_ConfigSampleModule (EADC_T *eadc, uint32_t u32ModuleNum, uint32_t u32TriggerSrc, uint32_t u32Channel) |
| Configure the sample control logic module. More... | |
| void | EADC_SetTriggerDelayTime (EADC_T *eadc, uint32_t u32ModuleNum, uint32_t u32TriggerDelayTime, uint32_t u32DelayClockDivider) |
| Set trigger delay time. More... | |
| void | EADC_SetInternalSampleTime (EADC_T *eadc, uint32_t u32SampleTime) |
| Set ADC internal sample time. More... | |
| void | EADC_SetExtendSampleTime (EADC_T *eadc, uint32_t u32ModuleNum, uint32_t u32ExtendSampleTime) |
| Set ADC extend sample time. More... | |
| #define EADC_CLR_INT_FLAG | ( | eadc, | |
| u32Mask | |||
| ) | ((eadc)->STATUS2 = (u32Mask)) |
Clear the selected interrupt status bits.
| [in] | eadc | The pointer of the specified EADC module. |
| [in] | u32Mask | The combination of compare interrupt status bits. Each bit corresponds to a compare interrupt status. Bit 0 is ADIF0, bit 1 is ADIF1..., bit 3 is ADIF3. Bit 4 is ADCMPF0, bit 5 is ADCMPF1..., bit 7 is ADCMPF3. |
This macro is used to clear clear the selected interrupt status bits.
| #define EADC_CLR_SAMPLE_MODULE_OV_FLAG | ( | eadc, | |
| u32ModuleMask | |||
| ) | ((eadc)->OVSTS = (u32ModuleMask)) |
Clear the selected sample module overrun status bits.
| [in] | eadc | The pointer of the specified EADC module. |
| [in] | u32ModuleMask | The combination of sample module overrun status bits. Each bit corresponds to a sample module overrun status. Bit 0 is SPOVF0, bit 1 is SPOVF1..., bit 18 is SPOVF18. |
This macro is used to clear the selected sample module overrun status bits.
| #define EADC_CONV_RESET | ( | eadc | ) | ((eadc)->CTL |= EADC_CTL_ADRST_Msk) |
| #define EADC_DISABLE_CMP0 | ( | eadc | ) | ((eadc)->CMP[0] = 0) |
| #define EADC_DISABLE_CMP1 | ( | eadc | ) | ((eadc)->CMP[1] = 0) |
| #define EADC_DISABLE_CMP2 | ( | eadc | ) | ((eadc)->CMP[2] = 0) |
| #define EADC_DISABLE_CMP3 | ( | eadc | ) | ((eadc)->CMP[3] = 0) |
| #define EADC_DISABLE_CMP_INT | ( | eadc, | |
| u32CMP | |||
| ) | ((eadc)->CMP[(u32CMP)] &= ~EADC_CMP_ADCMPIE_Msk) |
| #define EADC_DISABLE_CMP_WINDOW_MODE | ( | eadc, | |
| u32CMP | |||
| ) | ((eadc)->CMP[(u32CMP)] &= ~EADC_CMP_CMPWEN_Msk) |
Disable the compare window mode.
| [in] | eadc | The pointer of the specified EADC module. |
| [in] | u32CMP | Specifies the compare register, valid value are 0 and 2. |
ADCMPF2 (EADC_STATUS2[6]) will be set when both EADC_CMP2 and EADC_CMP3 compared condition matched.
| #define EADC_DISABLE_DOUBLE_BUFFER | ( | eadc, | |
| u32ModuleNum | |||
| ) | ((eadc)->SCTL[(u32ModuleNum)] &= ~EADC_SCTL_DBMEN_Msk) |
| #define EADC_DISABLE_INT | ( | eadc, | |
| u32Mask | |||
| ) | ((eadc)->CTL &= ~((u32Mask) << EADC_CTL_ADCIEN0_Pos)) |
Disable the interrupt.
| [in] | eadc | The pointer of the specified EADC module. |
| [in] | u32Mask | Decides the combination of interrupt status bits. Each bit corresponds to a interrupt status. This parameter decides which interrupts will be disabled. Bit 0 is ADCIEN0, bit 1 is ADCIEN1..., bit 3 is ADCIEN3. |
Specific sample module A/D ADINT0 interrupt function Disabled.
| #define EADC_DISABLE_INT_POSITION | ( | eadc, | |
| u32ModuleNum | |||
| ) | ((eadc)->SCTL[(u32ModuleNum)] &= ~EADC_SCTL_INTPOS_Msk) |
Set ADIFn at A/D start of conversion.
| [in] | eadc | The pointer of the specified EADC module. |
| [in] | u32ModuleNum | Decides the sample module number, valid value are from 0 to 15. |
The A/D converter generates ADIFn (EADC_STATUS2[3:0], n=0~3) at the end of conversion.
| #define EADC_DISABLE_PDMA | ( | eadc | ) | ((eadc)->CTL &= (~EADC_CTL_PDMAEN_Msk)) |
| #define EADC_DISABLE_SAMPLE_MODULE_INT | ( | eadc, | |
| u32IntSel, | |||
| u32ModuleMask | |||
| ) | ((eadc)->INTSRC[(u32IntSel)] &= ~(u32ModuleMask)) |
Disable the sample module interrupt.
| [in] | eadc | The pointer of the specified EADC module. |
| [in] | u32IntSel | Decides which interrupt source will be used, valid value are from 0 to 3. |
| [in] | u32ModuleMask | the combination of sample module interrupt status bits. Each bit corresponds to a sample module interrupt status. This parameter decides which sample module interrupts will be disabled, valid range are between 1~0x7FFFF. |
There are 4 ADC interrupts ADINT0~3, and each of these interrupts has its own interrupt vector address.
| #define EADC_ENABLE_CMP0 | ( | eadc, | |
| u32ModuleNum, | |||
| u32Condition, | |||
| u16CMPData, | |||
| u32MatchCount | |||
| ) |
Configure the comparator 0 and enable it.
| [in] | eadc | The pointer of the specified EADC module. |
| [in] | u32ModuleNum | specifies the compare sample module, valid value are from 0 to 18. |
| [in] | u32Condition | specifies the compare condition. Valid values are:
|
| [in] | u16CMPData | specifies the compare value, valid range are between 0~0xFFF. |
| [in] | u32MatchCount | specifies the match count setting, valid range are between 0~0xF. |
For example, ADC_ENABLE_CMP0(EADC, 5, ADC_ADCMPR_CMPCOND_GREATER_OR_EQUAL, 0x800, 10, EADC_CMP_CMPWEN_DISABLE, EADC_CMP_ADCMPIE_ENABLE); Means EADC will assert comparator 0 flag if sample module 5 conversion result is greater or equal to 0x800 for 10 times continuously, and a compare interrupt request is generated.
| #define EADC_ENABLE_CMP1 | ( | eadc, | |
| u32ModuleNum, | |||
| u32Condition, | |||
| u16CMPData, | |||
| u32MatchCount | |||
| ) |
Configure the comparator 1 and enable it.
| [in] | eadc | The pointer of the specified EADC module. |
| [in] | u32ModuleNum | specifies the compare sample module, valid value are from 0 to 18. |
| [in] | u32Condition | specifies the compare condition. Valid values are:
|
| [in] | u16CMPData | specifies the compare value, valid range are between 0~0xFFF. |
| [in] | u32MatchCount | specifies the match count setting, valid range are between 0~0xF. |
For example, ADC_ENABLE_CMP1(EADC, 5, ADC_ADCMPR_CMPCOND_GREATER_OR_EQUAL, 0x800, 10, EADC_CMP_ADCMPIE_ENABLE); Means EADC will assert comparator 1 flag if sample module 5 conversion result is greater or equal to 0x800 for 10 times continuously, and a compare interrupt request is generated.
| #define EADC_ENABLE_CMP2 | ( | eadc, | |
| u32ModuleNum, | |||
| u32Condition, | |||
| u16CMPData, | |||
| u32MatchCount | |||
| ) |
Configure the comparator 2 and enable it.
| [in] | eadc | The pointer of the specified EADC module. |
| [in] | u32ModuleNum | specifies the compare sample module, valid value are from 0 to 18. |
| [in] | u32Condition | specifies the compare condition. Valid values are:
|
| [in] | u16CMPData | specifies the compare value, valid range are between 0~0xFFF. |
| [in] | u32MatchCount | specifies the match count setting, valid range are between 0~0xF. |
For example, ADC_ENABLE_CMP2(EADC, 5, ADC_ADCMPR_CMPCOND_GREATER_OR_EQUAL, 0x800, 10, EADC_CMP_CMPWEN_DISABLE, EADC_CMP_ADCMPIE_ENABLE); Means EADC will assert comparator 2 flag if sample module 5 conversion result is greater or equal to 0x800 for 10 times continuously, and a compare interrupt request is generated.
| #define EADC_ENABLE_CMP3 | ( | eadc, | |
| u32ModuleNum, | |||
| u32Condition, | |||
| u16CMPData, | |||
| u32MatchCount | |||
| ) |
Configure the comparator 3 and enable it.
| [in] | eadc | The pointer of the specified EADC module. |
| [in] | u32ModuleNum | specifies the compare sample module, valid value are from 0 to 18. |
| [in] | u32Condition | specifies the compare condition. Valid values are:
|
| [in] | u16CMPData | specifies the compare value, valid range are between 0~0xFFF. |
| [in] | u32MatchCount | specifies the match count setting, valid range are between 1~0xF. |
For example, ADC_ENABLE_CMP3(EADC, 5, ADC_ADCMPR_CMPCOND_GREATER_OR_EQUAL, 0x800, 10, EADC_CMP_ADCMPIE_ENABLE); Means EADC will assert comparator 3 flag if sample module 5 conversion result is greater or equal to 0x800 for 10 times continuously, and a compare interrupt request is generated.
| #define EADC_ENABLE_CMP_INT | ( | eadc, | |
| u32CMP | |||
| ) | ((eadc)->CMP[(u32CMP)] |= EADC_CMP_ADCMPIE_Msk) |
Enable the compare interrupt.
| [in] | eadc | The pointer of the specified EADC module. |
| [in] | u32CMP | Specifies the compare register, valid value are from 0 to 3. |
If the compare function is enabled and the compare condition matches the setting of CMPCOND (EADC_CMPn[2], n=0~3) and CMPMCNT (EADC_CMPn[11:8], n=0~3), ADCMPFn (EADC_STATUS2[7:4], n=0~3) will be asserted, in the meanwhile, if ADCMPIE is set to 1, a compare interrupt request is generated.
| #define EADC_ENABLE_CMP_WINDOW_MODE | ( | eadc, | |
| u32CMP | |||
| ) | ((eadc)->CMP[(u32CMP)] |= EADC_CMP_CMPWEN_Msk) |
Enable the compare window mode.
| [in] | eadc | The pointer of the specified EADC module. |
| [in] | u32CMP | Specifies the compare register, valid value are 0 and 2. |
ADCMPF0 (EADC_STATUS2[4]) will be set when both EADC_CMP0 and EADC_CMP1 compared condition matched.
| #define EADC_ENABLE_DOUBLE_BUFFER | ( | eadc, | |
| u32ModuleNum | |||
| ) | ((eadc)->SCTL[(u32ModuleNum)] |= EADC_SCTL_DBMEN_Msk) |
Enable double buffer mode.
| [in] | eadc | The pointer of the specified EADC module. |
| [in] | u32ModuleNum | Decides the sample module number, valid value are from 0 to 3. |
The ADC controller supports a double buffer mode in sample module 0~3. If user enable DBMEN (EADC_SCTLn[23], n=0~3), the double buffer mode will enable.
| #define EADC_ENABLE_INT | ( | eadc, | |
| u32Mask | |||
| ) | ((eadc)->CTL |= ((u32Mask) << EADC_CTL_ADCIEN0_Pos)) |
Enable the interrupt.
| [in] | eadc | The pointer of the specified EADC module. |
| [in] | u32Mask | Decides the combination of interrupt status bits. Each bit corresponds to a interrupt status. This parameter decides which interrupts will be enabled. Bit 0 is ADCIEN0, bit 1 is ADCIEN1..., bit 3 is ADCIEN3. |
The A/D converter generates a conversion end ADIFn (EADC_STATUS2[n]) upon the end of specific sample module A/D conversion. If ADCIENn bit (EADC_CTL[n+2]) is set then conversion end interrupt request ADINTn is generated (n=0~3).
| #define EADC_ENABLE_INT_POSITION | ( | eadc, | |
| u32ModuleNum | |||
| ) | ((eadc)->SCTL[(u32ModuleNum)] |= EADC_SCTL_INTPOS_Msk) |
Set ADIFn at A/D end of conversion.
| [in] | eadc | The pointer of the specified EADC module. |
| [in] | u32ModuleNum | Decides the sample module number, valid value are from 0 to 15. |
The A/D converter generates ADIFn (EADC_STATUS2[3:0], n=0~3) at the start of conversion.
| #define EADC_ENABLE_PDMA | ( | eadc | ) | ((eadc)->CTL |= EADC_CTL_PDMAEN_Msk) |
Enable PDMA transfer.
| [in] | eadc | The pointer of the specified EADC module. |
When A/D conversion is completed, the converted data is loaded into EADC_DATn (n: 0 ~ 18) register, user can enable this bit to generate a PDMA data transfer request.
| #define EADC_ENABLE_SAMPLE_MODULE_INT | ( | eadc, | |
| u32IntSel, | |||
| u32ModuleMask | |||
| ) | ((eadc)->INTSRC[(u32IntSel)] |= (u32ModuleMask)) |
Enable the sample module interrupt.
| [in] | eadc | The pointer of the specified EADC module. |
| [in] | u32IntSel | Decides which interrupt source will be used, valid value are from 0 to 3. |
| [in] | u32ModuleMask | the combination of sample module interrupt status bits. Each bit corresponds to a sample module interrupt status. This parameter decides which sample module interrupts will be enabled, valid range are between 1~0x7FFFF. |
There are 4 ADC interrupts ADINT0~3, and each of these interrupts has its own interrupt vector address.
| #define EADC_GET_CONV_DATA | ( | eadc, | |
| u32ModuleNum | |||
| ) | ((eadc)->DAT[(u32ModuleNum)] & EADC_DAT_RESULT_Msk) |
Get the conversion data of the user-specified sample module.
| [in] | eadc | The pointer of the specified EADC module. |
| [in] | u32ModuleNum | Decides the sample module number, valid value are from 0 to 18. |
This macro is used to read RESULT bit (EADC_DATn[15:0], n=0~18) field to get conversion data.
| #define EADC_GET_DATA_OVERRUN_FLAG | ( | eadc, | |
| u32ModuleMask | |||
| ) | ((((eadc)->STATUS0 >> EADC_STATUS0_OV_Pos) | ((eadc)->STATUS1 & EADC_STATUS1_OV_Msk)) & (u32ModuleMask)) |
Get the data overrun flag of the user-specified sample module.
| [in] | eadc | The pointer of the specified EADC module. |
| [in] | u32ModuleMask | The combination of data overrun status bits. Each bit corresponds to a data overrun status, valid range are between 1~0x7FFFF. |
This macro is used to read OV bit (EADC_STATUS0[31:16], EADC_STATUS1[18:16]) field to get data overrun status.
| #define EADC_GET_DATA_VALID_FLAG | ( | eadc, | |
| u32ModuleMask | |||
| ) | ((((eadc)->STATUS0 & EADC_STATUS0_VALID_Msk) | (((eadc)->STATUS1 & EADC_STATUS1_VALID_Msk) << 16)) & (u32ModuleMask)) |
Get the data valid flag of the user-specified sample module.
| [in] | eadc | The pointer of the specified EADC module. |
| [in] | u32ModuleMask | The combination of data valid status bits. Each bit corresponds to a data valid status, valid range are between 1~0x7FFFF. |
This macro is used to read VALID bit (EADC_STATUS0[15:0], EADC_STATUS1[1:0]) field to get data overrun status.
| #define EADC_GET_DOUBLE_DATA | ( | eadc, | |
| u32ModuleNum | |||
| ) | ((eadc)->DDAT[(u32ModuleNum)] & EADC_DDAT_RESULT_Msk) |
Get the double data of the user-specified sample module.
| [in] | eadc | The pointer of the specified EADC module. |
| [in] | u32ModuleNum | Decides the sample module number, valid value are from 0 to 18. |
This macro is used to read RESULT bit (EADC_DDATn[15:0], n=0~3) field to get conversion data.
| #define EADC_GET_INT_FLAG | ( | eadc, | |
| u32Mask | |||
| ) | ((eadc)->STATUS2 & (u32Mask)) |
Get the user-specified interrupt flags.
| [in] | eadc | The pointer of the specified EADC module. |
| [in] | u32Mask | The combination of interrupt status bits. Each bit corresponds to a interrupt status. Bit 0 is ADIF0, bit 1 is ADIF1..., bit 3 is ADIF3. Bit 4 is ADCMPF0, bit 5 is ADCMPF1..., bit 7 is ADCMPF3. |
This macro is used to get the user-specified interrupt flags.
| #define EADC_GET_PENDING_CONV | ( | eadc | ) | ((eadc)->PENDSTS) |
Get the conversion pending flag.
| [in] | eadc | The pointer of the specified EADC module. |
This STPFn(EADC_PENDSTS[18:0]) bit remains 1 during pending state, when the respective ADC conversion is end, the STPFn (n=0~18) bit is automatically cleared to 0.
| #define EADC_GET_SAMPLE_MODULE_OV_FLAG | ( | eadc, | |
| u32ModuleMask | |||
| ) | ((eadc)->OVSTS & (u32ModuleMask)) |
Get the user-specified sample module overrun flags.
| [in] | eadc | The pointer of the specified EADC module. |
| [in] | u32ModuleMask | The combination of sample module overrun status bits. Each bit corresponds to a sample module overrun status, valid range are between 1~0x7FFFF. |
This macro is used to get the user-specified sample module overrun flags.
| #define EADC_IS_BUSY | ( | eadc | ) | (((eadc)->STATUS2 & EADC_STATUS2_BUSY_Msk) >> EADC_STATUS2_BUSY_Pos) |
| #define EADC_IS_DATA_OV | ( | eadc | ) | (((eadc)->STATUS2 & EADC_STATUS2_AOV_Msk) >> EADC_STATUS2_AOV_Pos) |
Check all sample module A/D result data register overrun flags.
| [in] | eadc | The pointer of the specified EADC module. |
| 0 | None of sample module data register overrun flag is set to 1. |
| 1 | Any one of sample module data register overrun flag is set to 1. |
The AOV bit (EADC_STATUS2[27]) will keep 1 when any one of sample module data register overrun flag OVn (EADC_DATn[16]) is set to 1.
| #define EADC_IS_DATA_VALID | ( | eadc | ) | (((eadc)->STATUS2 & EADC_STATUS2_AVALID_Msk) >> EADC_STATUS2_AVALID_Pos) |
Check all sample module A/D result data register valid flags.
| [in] | eadc | The pointer of the specified EADC module. |
| 0 | None of sample module data register valid flag is set to 1. |
| 1 | Any one of sample module data register valid flag is set to 1. |
The AVALID bit (EADC_STATUS2[26]) will keep 1 when any one of sample module data register valid flag VALIDn (EADC_DATn[17]) is set to 1.
| #define EADC_IS_INT_FLAG_OV | ( | eadc | ) | (((eadc)->STATUS2 & EADC_STATUS2_ADOVIF_Msk) >> EADC_STATUS2_ADOVIF_Pos) |
Check all A/D interrupt flag overrun bits.
| [in] | eadc | The pointer of the specified EADC module. |
| 0 | None of ADINT interrupt flag is overwritten to 1. |
| 1 | Any one of ADINT interrupt flag is overwritten to 1. |
The ADOVIF bit (EADC_STATUS2[24]) will keep 1 when any one of ADINT interrupt flag ADOVIFn (EADC_STATUS2[11:8]) is overwritten to 1.
| #define EADC_IS_SAMPLE_MODULE_OV | ( | eadc | ) | (((eadc)->STATUS2 & EADC_STATUS2_STOVF_Msk) >> EADC_STATUS2_STOVF_Pos) |
Check all A/D sample module start of conversion overrun flags.
| [in] | eadc | The pointer of the specified EADC module. |
| 0 | None of sample module event overrun flag is set to 1. |
| 1 | Any one of sample module event overrun flag is set to 1. |
The STOVF bit (EADC_STATUS2[25]) will keep 1 when any one of sample module event overrun flag SPOVFn (EADC_OVSTS[n]) is set to 1.
| #define EADC_SET_DMOF | ( | eadc, | |
| u32Format | |||
| ) | ((eadc)->CTL = ((eadc)->CTL & ~EADC_CTL_DMOF_Msk) | (u32Format)) |
Set the input mode output format.
| [in] | eadc | The pointer of the specified EADC module. |
| [in] | u32Format | Decides the output format. Valid values are:
|
The macro is used to set A/D input mode output format.
| #define EADC_START_CONV | ( | eadc, | |
| u32ModuleMask | |||
| ) | ((eadc)->SWTRG = (u32ModuleMask)) |
Start the A/D conversion.
| [in] | eadc | The pointer of the specified EADC module. |
| [in] | u32ModuleMask | The combination of sample module. Each bit corresponds to a sample module. This parameter decides which sample module will be conversion, valid range are between 1~0x7FFFF. Bit 0 is sample module 0, bit 1 is sample module 1..., bit 18 is sample module 18. |
After write EADC_SWTRG register to start ADC conversion, the EADC_PENDSTS register will show which SAMPLE will conversion.
| #define EADC_STOP_CONV | ( | eadc, | |
| u32ModuleMask | |||
| ) | ((eadc)->PENDSTS = (u32ModuleMask)) |
Cancel the conversion for sample module.
| [in] | eadc | The pointer of the specified EADC module. |
| [in] | u32ModuleMask | The combination of sample module. Each bit corresponds to a sample module. This parameter decides which sample module will stop the conversion, valid range are between 1~0x7FFFF. Bit 0 is sample module 0, bit 1 is sample module 1..., bit 18 is sample module18. |
If user want to disable the conversion of the sample module, user can write EADC_PENDSTS register to clear it.
| void EADC_Close | ( | EADC_T * | eadc | ) |
| void EADC_ConfigSampleModule | ( | EADC_T * | eadc, |
| uint32_t | u32ModuleNum, | ||
| uint32_t | u32TriggerSrc, | ||
| uint32_t | u32Channel | ||
| ) |
Configure the sample control logic module.
| [in] | eadc | The pointer of the specified EADC module. |
| [in] | u32ModuleNum | Decides the sample module number, valid value are from 0 to 15. |
| [in] | u32TriggerSrc | Decides the trigger source. Valid values are:
|
| [in] | u32Channel | Specifies the sample module channel, valid value are from 0 to 15. |
Each of ADC control logic modules 0~15 which is configurable for ADC converter channel EADC_CH0~15 and trigger source. sample module 16~18 is fixed for ADC channel 16, 17, 18 input sources as band-gap voltage, temperature sensor, and battery power (VBAT).
| void EADC_Open | ( | EADC_T * | eadc, |
| uint32_t | u32InputMode | ||
| ) |
This function make EADC_module be ready to convert.
| [in] | eadc | The pointer of the specified EADC module. |
| [in] | u32InputMode | Decides the input mode.
|
This function is used to set analog input mode and enable A/D Converter. Before starting A/D conversion function, ADCEN bit (EADC_CTL[0]) should be set to 1.
| void EADC_SetExtendSampleTime | ( | EADC_T * | eadc, |
| uint32_t | u32ModuleNum, | ||
| uint32_t | u32ExtendSampleTime | ||
| ) |
Set ADC extend sample time.
| [in] | eadc | The pointer of the specified EADC module. |
| [in] | u32ModuleNum | Decides the sample module number, valid value are from 0 to 18. |
| [in] | u32ExtendSampleTime | Decides the extend sampling time, the range is from 0~255 ADC clock. Valid value are from 0 to 0xFF. |
When A/D converting at high conversion rate, the sampling time of analog input voltage may not enough if input channel loading is heavy, user can extend A/D sampling time after trigger source is coming to get enough sampling time.
| void EADC_SetInternalSampleTime | ( | EADC_T * | eadc, |
| uint32_t | u32SampleTime | ||
| ) |
Set ADC internal sample time.
| [in] | eadc | The pointer of the specified EADC module. |
| [in] | u32SampleTime | Decides the internal sampling time, the range is from 1~8 ADC clock. Valid value are from 1 to 8. |
When A/D operation at high ADC clock rate, the sampling time of analog input voltage may not enough if the analog channel has heavy loading to cause fully charge time is longer. User can set SMPTSEL (EADC_CTL[18:16]) to select the sampling cycle in ADC.
| void EADC_SetTriggerDelayTime | ( | EADC_T * | eadc, |
| uint32_t | u32ModuleNum, | ||
| uint32_t | u32TriggerDelayTime, | ||
| uint32_t | u32DelayClockDivider | ||
| ) |
Set trigger delay time.
| [in] | eadc | The pointer of the specified EADC module. |
| [in] | u32ModuleNum | Decides the sample module number, valid value are from 0 to 15. |
| [in] | u32TriggerDelayTime | Decides the trigger delay time, valid range are between 0~0xFF. |
| [in] | u32DelayClockDivider | Decides the trigger delay clock divider. Valid values are:
|
User can configure the trigger delay time by setting TRGDLYCNT (EADC_SCTLn[15:8], n=0~15) and TRGDLYDIV (EADC_SCTLn[7:6], n=0~15). Trigger delay time = (u32TriggerDelayTime) x Trigger delay clock period.


| Inclusive Software, Inc. |
| Product: |
Momentum[tm] |
| Description: |
Momentum is the planning and tracking tool for the
electronics industry and is used throughout the entire product
lifecycle. Using Momentum, a product team can quickly put together a
product concept and definition, shorten the product's approval
process, and manage the product through its lifecycle.
|
| System Requirements: |
- Operating System: Windows XP, Windows 2000, Windows ME, Windows NT 4.0
Service Pack 6, or Windows 98 SE
- RAM: 128 MBs (minimum); 256 MBs (recommended)
- Network Card: 10 MIPS (minimum); 10/100 MIPS (recommended)
|
| Availability & Pricing: |
A pre-release program is currently underway;
the commercial release is scheduled for Summer, 2002. |
| Target Markets: |
Electronics industry |
| Contact: |
Steve Strom
Senior Product Manager
<EMAIL_ADDRESS>Phone:<PHONE_NUMBER> ext. 224 |
| Website: |
http://www.InclusiveSoftware.com |
|


Sorry, Web Serial is not supported on this device, make sure you are:
- running Chrome 78 or later
- have enabled
the
#enable-experimental-web-platform-features
flag inchrome://flags
- loading the page from an HTTP server (the WebSerial API
is not enabled for pages loaded from
a
file://
URL).
Python's simple HTTP server (python3 -m http.server
) is good enough.
| Gamma: | ||
|---|---|---|
| Red: | ||
| Green: | ||
| Blue: |


The computer science club is the driving force behind software design and website development at Rockland Community College. We are an experienced group of coders and hobbyists who all enjoy one thing in common-- computers. We welcome all new members and love new ideas! If you ever wanted to make a website, or have a great idea for an app and don’t know where to get started, sit in for a meeting! You would be surprised at what a diverse, intelligent community we have here at the Computer Science Club.
- Matthew PeckoPresident
- Dorian BacharachVice-President
- Alex GoldsteinTreasurer
- Brandon HlavacSecretary
- Merik Emmanuel
- Dean Sacks
- Matthew Ljuljic
- Shayna Rosado
- Abraham Gross
- Sambo Jailes
- Janina Dizon
- Anna Proctor
- Brian Cisneros
- Lionel Janbert
- Jonathan Jacques
- Linda Sunny
- Skyler Young
- Felipe Gallaudo
- Nautika Clemens
- Lynn AaronOrganizer
Interested in joining?
The Computer Science Club is always excited for new recruits. We meet every Tuesday and Thursday from 12:30 to 1:20pm in room 8375 in the Technology Building, third floor. Come stop by! (we have candy :)


HSP : Hot Soup Processor ver3.6 / onion software 1997-2021(c)
HSP3 for Linux / Raspberry Pi is a development environment for Hot Soup Processor (HSP) that runs on Linux GUI environment (X Window System) and Raspberry Pi (Raspbian).
Development is proceeding with the aim of supporting the development environment of HSP3 on Linux, which is inexpensive and has a wide range of environments.
Raspberry Pi is attracting attention in the fields of IoT and programming education as a very compact and inexpensive device. I am.
Even now, we have prepared the execution environment for Android, iOS, WebGL (html5), etc. through the runtime HSP3Dish as well as Windows. ,
We will newly improve it so that it can be used in Linux and Raspbian (OS on Raspberry Pi) environment.
As the first version, we have released a preview version that includes a simple script editor and the HSP3Dish / HGIMG4 execution environment.
We plan to expand support with HSP3 for Windows, so please look forward to it.
The latest version is available on github with the source code.
If you are using Raspberry Pi, please go to JBOYSOFT's "Introduction to Beginners HSP Programming Raspberry Pi Version" page The introduction is explained.
| Introduction to beginners HSP programming Raspberry Pi version by JBOYSOFT > |
It works in the Linux GUI environment (X Window System). Some features work using OpenGL and SDL libraries. If you can connect to the network, get the repository directly with the git command.
git clone http://github.com/onitama/OpenHSP
If you have an archive, extract the contents to any directory and compile the source. To compile, you need an environment where you can run gcc and make. The following libraries are required when compiling, so please check in advance.
OpenGL ES2.0 or later / EGL SDL1.2 gtk+-2
For Debian (Ubuntu), you can install the library from the package manager as follows.
sudo apt-get update sudo apt-get install libgtk2.0-dev sudo apt-get install libglew-dev sudo apt-get install libsdl1.2-dev libsdl-image1.2-dev libsdl-mixer1.2-dev libsdl-ttf2.0-dev sudo apt-get install libgles2-mesa-dev libegl1-mesa-dev
The repository contains only the source, so you need to compile it with make. (If it doesn't compile correctly depending on your Linux version or distribution, you'll need to fix it.)
cd OpenHSP make
The necessary tools have been compiled and HSP3 is ready for use.
It runs on Raspberry Pi, Raspberry Pi2, Raspberry Pi3, Raspberry Pi4, Raspberry Pi zeo.
It runs on Raspbian OS. (Recommended version is September 2017 Kernel version 4.9 or later)
Please use it with Raspbian running and a keyboard and mouse connected in advance.
hsp3dish, hsp3gp (HGIMG4) and hsed (script editor) only work in GUI environment.
Extract the latest version from github to any directory and compile the source. To compile, you need an environment where you can run gcc and make.
git clone http://github.com/onitama/OpenHSP cd OpenHSP
Additional libraries are required when compiling. Setup is executed by executing the following command while connected to the network.
./pisetup.sh
The archive contains only the sources and must be compiled by make. (If it doesn't compile correctly depending on the version or distribution of Raspbian, you need to fix it.)
make -f makefile.raspbian
Execute the make command in the directory where the contents of the archive are expanded.
The necessary tools have been compiled and HSP3 is ready for use.
* For Raspberry Pi4, please install with make in the same way as Linux. * Raspberry Pi 4 does not support full-screen execution
After installation, the following command will be generated.
hsed script editor (simplified version) hspcmp HSP3 code compiler hsp3cl HSP3 command line runtime hsp3dish HSP3Dish runtime hsp3gp HGIM G4 runtime
Script Editor (Simplified Version) is a GUI application that allows you to write and execute HSP3 scripts. It has basic script editing and load / save functions. You can start it with the following command.
./hsed
You can run the script you are editing by pressing the [F5] key or selecting "Run" from the "HSP" menu.
The current version uses hsp3dish as the standard runtime.
The sample code corresponding to HSP3Dish is included in the sample folder, so please try it.
The character code of the script is treated as UTF-8. Please note that it is different from the character code (SJIS) used by Windows.
If you want to execute the script from the command line, you need to create an HSP object file with hspcmp.
./hspcmp -d -i -u test.hsp
In the above example, the object file "test.ax" is generated from the "test.hsp" file. Pass the generated object file to the runtime for execution.
./hsp3cl test.ax
In the above example, "test.ax" is run at the HSP3 command line runtime.
Similarly, you can execute scripts tailored to the runtime such as "hsp3dish" and "hsp3gp".
(A GUI environment is required to execute "hsp3dish" and "hsp3gp".)
The Raspberry Pi version runs in full screen. To interrupt the execution, press [ctrl] + [C] or [esc]. Please note that you may not be able to interrupt if the keyboard is not recognized correctly. In addition to the GUI editor, it is also possible to execute in the form of "./hsp3dish ****. Ax" from the command line.
| Go to the HSP3Dish page | |
| HSP3Dish Online Manual |
Both the Linux version and the Raspberry Pi version can call shell commands with the exec command. It is also possible to output a character string to a device on the file system with the devprm instruction.
devprm "/sys/class/gpio/export", "2"
If you write like, "2" will be output to "/ sys / class / gpio / export". It works the same as running "echo 2> / sys / class / gpio / export" from the shell.
In Raspberry Pi version, GPIO input / output is extended by devcontrol (gpio) instruction.
To control GPIO output, write as follows.
devcontrol "gpio", port number, output value (It can also be described as "gpio port number, output value")
For the port number, specify the GPIO port numerically. For the output value, specify 1 (ON) or 0 (OFF) as a numerical value to control the output of the digital port. When inputting, describe as follows.
devcontrol "gpioin", port number (It is also possible to write "gpioin (port number)" as a function)
The system variable stat is assigned 0 or 1 after the instruction is executed.
(If an error occurs, a negative value will be assigned.)
GPIO input / output can be used not only from hsp3dish but also from hsp3cl.
In the Raspberry Pi version, the extension to input / output with the I2C device is done by the devcontrol (i2c ~) command.
For I2C control, I2C must be enabled in the Raspberry Pi option settings. (If I2C control is not performed, no setting is required.) When I2C control is performed, describe as follows.
devcontrol "i2copen", slave address, channel (It can also be described as "i2copen slave address, channel") "Channel" is a number that identifies when multiple devices are specified at the same time. (Integer value from 0 to 31) It can be omitted (0) when controlling a single device. i2copen will be able to control the device at the specified address. The result is returned in the system variable stat. If it is 0, it will be successful, otherwise it will be an error.
To output the data, write as follows.
devcontrol "i2cwrite", data value, data size, channel (It can also be described as "i2c write data value, data size, channel") The data value is a 32-bit integer value handled by HSP. If the data size is 0 or omitted, only 8bit (1byte) is output. The data size can be 1,2,3,4. The size of 1 to 4 bytes is output for each.
When entering the data, write as follows.
devcontrol "i2cread", channel (It is also possible to write "i2cread (channel)" as a function) devcontrol "i2creadw", channel (It is also possible to write "i2creadw (channel)" as a function)
The result is assigned to the system variable stat after the instruction is executed. i2cread gets the value of 8bit (1byte), and i2creadw gets the value of 16bit (2byte). (If an error occurs, a negative value will be assigned.) I2C control can be used not only from hsp3dish but also from hsp3cl.
HSP3 for Linux / Raspberry Pi is treated as a derivative of OpenHSP, and the license is also a modified BSD license compliant with OpenHSP / HSP3.
------------------------------------------------------------------------------- Hot Soup Processor (HSP) Copyright (C) 1997-2021, Onion Software/onitama, all rights reserved. Made with base technology of OpenHSP. OpenHSP Copyright (C) 1997-2021, Onion Software/onitama, all rights reserved. These softwares are provided by the copyright holders and contributors "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose are disclaimed.


Converting equirectangular image to fisheye image¶
What is an equirectangular image?
Converting equirectangular image to fisheye image It is a method of representing the curved spherical 3D world on a 2D plane in the form of longitudes and latitudes. An equirectangular image is always in a 2:1 ratio. Equirectangular images are relatively easy to visualize and are also in the form of a rectangular image. It is not only used to create 2D world maps but also to represent imagery from a full sphere rather than just a small window onto the world.[1]
Converting an equirectangular image to fisheye image¶
For converting an equirectangular image to a fisheye image, the equirectangular image is considered to be projected on a unit sphere using the equivalent longitude and latitude coordinates of the equirectangular image and then this information is later projected on an imaging plane based on a camera model. There are several camera models proposed in the literature. OmniCV library provides implementations for several types of camera models which include the Unified Camera Model (UCM) [5], Extended Unified Camera Model (EUCM) [6], Field Of View (FOV) Camera model [7] and Double Sphere Camera Model [3].
The code for Unified Camera Model is inspired from, DeepCalib[2] and its github repository. The repository provides python which can be further modified and used for desired purpose.
Python Example¶
-
fisheyeImgConv.
equirect2Fisheye_UCM
(img,outShape,f=50,xi=1.2,angles=[0,0,0])¶ Function to convert equirectangular image to fisheye image using the unified camera model (UCM).
- Parameters
img – Input equirectangular image
outShape – list of [Image_Height,Image_Width] in pixels
f – Focal lenght
xi – Distortion coefficient
angles – List of camera [roll,pitch,yaw]
- Return type
Numpy array
-
fisheyeImgConv.
equirect2Fisheye_EUCM
(img,outShape,f=50,a_=0.5,b_=0.5,angles=[0,0,0])¶ Function to convert equirectangular image to fisheye image using the extended unified camera model (EUCM).
- Parameters
img – Input equirectangular image
outShape – list of [Image_Height,Image_Width] in pixels
f – Focal lenght
a – Distortion coefficient
b – Distortion coefficient
angles – List of camera [roll,pitch,yaw]
- Return type
Numpy array
-
fisheyeImgConv.
equirect2Fisheye_FOV
(img,outShape,f=50,w_=0.5,angles=[0,0,0])¶ Function to convert equirectangular image to fisheye image using the Field of View (FOV) camera model.
- Parameters
img – Input equirectangular image
outShape – list of [Image_Height,Image_Width] in pixels
f – Focal lenght
w – Distortion coefficient
angles – List of camera [roll,pitch,yaw]
- Return type
Numpy array
-
fisheyeImgConv.
equirect2Fisheye_DS
(img,outShape,f=50,a_=0.5,xi_=0.5,angles=[0,0,0])¶ Function to convert equirectangular image to fisheye image using the Double Sphere (DS) camera model.
- Parameters
img – Input equirectangular image
outShape – list of [Image_Height,Image_Width] in pixels
f – Focal lenght
a – Distortion coefficient
xi – Distortion coefficient
angles – List of camera [roll,pitch,yaw]
- Return type
Numpy array
Example code
#!/usr/bin/env/python
import cv2
import numpy as np
import math
import time
import sys
from omnicv import fisheyeImgConv
# Import equirectangular image
equiRect = cv2.imread(IMAGE_PATH)
# Defining output shape
outShape = [250,250]
# Creating mapper object
mapper = fisheyeImgConv()
# Converting equirectangular to fisheye using Unified Camera model (UCM)
fisheye = mapper.equirect2Fisheye_UCM(equiRect,outShape=outShape,xi=0.5)
cv2.imshow("UCM Model Output",fisheye)
cv2.waitKey(0)
# Converting equirectangular to fisheye using Extended UCM model
fisheye = mapper.equirect2Fisheye_EUCM(equiRect,outShape=[250,250],f=100,a_=0.4,b_=2,angles=[0,0,0])
cv2.imshow("EUCM Model Output",fisheye)
cv2.waitKey(0)
# Converting equirectangular to fisheye using Field Of Vide (FOV) model
fisheye = mapper.equirect2Fisheye_FOV(equiRect,outShape=[250,250],f=40,w_=0.5,angles=[0,0,0])
cv2.imshow("FOV model Output",fisheye)
cv2.waitKey(0)
# Converting equirectangular to fisheye using Double Sphere (DS) model
fisheye = mapper.equirect2Fisheye_DS(equiRect,outShape=[250,250],f=90,a_=0.4,xi_=0.8,angles=[0,0,0])
cv2.imshow("DS Model Output",fisheye)
cv2.waitKey(0)
# Changing the distortion coefficient for (UCM)
fisheye = mapper.equirect2Fisheye(equiRect,outShape=outShape,xi=0.2)
cv2.imshow("fisheye",fisheye)
cv2.waitKey(0)
# Rotate the sphere
fisheye = mapper.equirect2Fisheye(equiRect,outShape=outShape,angles=[90,0,0])
cv2.imshow("fisheye",fisheye)
cv2.waitKey(0)
C++ Example¶
-
fisheyeImgConv::equirect2Fisheye_UCM(const cv::Mat &img, cv::Mat &dstFrame, cv::Size outShape,
-
float f=50, float xi=1.2,float alpha=0, float beta=0, float gamma=0);
Function to convert equirectangular image to fisheye image using the unified camera model (UCM).
- Parameters
img – Input equirectangular image.
outShape – list of [Image_Height,Image_Width] in pixels.
f – Focal lenght.
xi – Distortion coefficient.
alpha – Rotation of camera about X axis.
beta – Rotation of camera about Y axis.
gamma – Rotation of camera about Z axis.
dstFrame – Output image.
-
fisheyeImgConv::equirect2Fisheye_EUCM(const cv::Mat &img, cv::Mat &dstFrame, cv::Size outShape, float f=50,
-
float a_ = 0.5, float b_=0.5, float alpha=0, float beta=0, float gamma=0);
Function to convert equirectangular image to fisheye image using the extended unified camera model (EUCM).
- Parameters
img – Input equirectangular image.
outShape – list of [Image_Height,Image_Width] in pixels.
f – Focal lenght.
a – Distortion coefficient.
b – Distortion coefficient.
alpha – Rotation of camera about X axis.
beta – Rotation of camera about Y axis.
gamma – Rotation of camera about Z axis.
dstFrame – Output image.
-
fisheyeImgConv::equirect2Fisheye_FOV(const cv::Mat &img, cv::Mat &dstFrame, cv::Size outShape, float f=50,
-
float w_=0.5, float alpha=0, float beta=0, float gamma=0);
Function to convert equirectangular image to fisheye image using the Field of View (FOV) camera model.
- Parameters
img – Input equirectangular image.
outShape – list of [Image_Height,Image_Width] in pixels.
f – Focal lenght.
w – Distortion coefficient.
alpha – Rotation of camera about X axis.
beta – Rotation of camera about Y axis.
gamma – Rotation of camera about Z axis.
dstFrame – Output image.
-
fisheyeImgConv::equirect2Fisheye_DS(const cv::Mat &img, cv::Mat &dstFrame, cv::Size outShape, float f=50,
-
float a_ = 0.5, float xi_=0.5, float alpha=0, float beta=0, float gamma=0);
Function to convert equirectangular image to fisheye image using the Double Sphere (DS) camera model.
- Parameters
img – Input equirectangular image.
outShape – list of [Image_Height,Image_Width] in pixels.
f – Focal lenght.
a – Distortion coefficient.
xi – Distortion coefficient.
alpha – Rotation of camera about X axis.
beta – Rotation of camera about Y axis.
gamma – Rotation of camera about Z axis.
dstFrame – Output image.
Example code
#include<iostream>
#include<opencv2/opencv.hpp>
#include"../omnicv/utils.hpp"
#include <opencv2/core/core.hpp>
// Creating the display window
int H = 500;
int W = 500;
std::string WINDOW_NAME{"viewer"};
int main()
{
cv::namedWindow(WINDOW_NAME,CV_WINDOW_NORMAL);
// cv::resizeWindow(WINDOW_NAME, 400, 400);
cv::Mat frame;
cv::Mat outFrame;
// ##### 1. Example for equirectangular to fisheye image conversion using Unified camera model ##########
frame = cv::imread("../data/equirect_temp1.jpg");
cv::imshow(WINDOW_NAME,frame);
cv::waitKey(0);
fisheyeImgConv mapper1;
mapper1.equirect2Fisheye_UCM(frame,outFrame, cv::Size (250,250),100,0.9);
cv::imshow("Unified Camera Model model output",outFrame);
cv::waitKey(0);
// ##### 2. Example for equirectangular to fisheye image conversion using Extended Unified camera model ##########
frame = cv::imread("../data/equirect_temp1.jpg");
cv::imshow(WINDOW_NAME,frame);
cv::waitKey(0);
fisheyeImgConv mapper1;
mapper1.equirect2Fisheye_EUCM(frame,outFrame, cv::Size (250,250),100,0.4,2);
cv::imshow("Extended Unified Camera Model model output",outFrame);
cv::waitKey(0);
// ##### 3. Example for equirectangular to fisheye image conversion using Field of View camera model ##########
frame = cv::imread("../data/equirect_temp1.jpg");
cv::imshow(WINDOW_NAME,frame);
cv::waitKey(0);
fisheyeImgConv mapper1;
mapper1.equirect2Fisheye_FOV(frame,outFrame, cv::Size (250,250),50,1.2);
cv::imshow("Field of View model output",outFrame);
cv::waitKey(0);
// ##### 4. Example for equirectangular to fisheye image conversion using Double Sphere camera model ##########
frame = cv::imread("../data/equirect_temp1.jpg");
cv::imshow(WINDOW_NAME,frame);
cv::waitKey(0);
fisheyeImgConv mapper1;
mapper1.equirect2Fisheye_DS(frame,outFrame, cv::Size (250,250),50,0.4,0.8);
cv::imshow("Double Sphere model output",outFrame);
cv::waitKey(0);
return 0;
}
Results¶
refer to the example code. to know the other ways of using this conversion
Reference¶
[1] Google AR VR blog - https://blog.google/products/google-vr/bringing-pixels-front-and-center-vr-video/
[2] Bogdan, Oleksandr & Eckstein, Viktor & Rameau, François & Bazin, Jean-Charles. (2018). DeepCalib: a deep learning approach for automatic intrinsic calibration of wide field-of-view cameras. 1-10. 10.1145/3278471.3278479.
[3] Usenko, Vladyslav & Demmel, Nikolaus & Cremers, Daniel. (2018). The Double Sphere Camera Model.
[4] Kannala, Juho & Brandt, Sami. (2006). A Generic Camera Model and Calibration Method for Conventional, Wide-Angle, and Fish-Eye Lenses. IEEE transactions on pattern analysis and machine intelligence. 28. 1335-40. 10.1109/TPAMI.2006.153.
[5] C. Geyer and K. Daniilidis. A unifying theory for central panoramic systems and practical implications. In D.Vernon, editor, Computer Vision — ECCV 2000, pages 445–461, Berlin, Heidelberg, 2000. Springer Berlin Heidelberg.
[6] B. Khomutenko, G. Garcia, and P. Martinet. An enhanced unified camera model. IEEE Robotics and Automation Letters, 1(1):137–144, Jan 2016.
[7] F. Devernay and O. Faugeras. Straight lines have to be straight. Machine vision and applications, 13(1):14–24, 2001.


--- layout: post title: Hello MSDN Mag Readers date: '2007-10-17T13:20:00.001-07:00' author: Kevin Moore tags: - WPF - Programming - MIX07 - Microsoft modified_time: '2007-10-17T13:20:00.146-07:00' blogger_id: tag:blogger.com,1999:blog-2115056243892631308.post-8806237599661623691 blogger_orig_url: http://work.j832.com/2007/10/hello-msdn-mag-readers.html ---
I kinda forgot I wrote this article in August.
I guess the sudden increase in emails makes sense.
In case it got buried, I am no longer at Microsoft, but you can still find the bag-o-tricks here.
I've taken a pretty big break from most things WPF. If you have questions, you're best bet is the WPF MSDN forum.
Hope you enjoyed my attempt at wit and wisdom.


Tests: Particle, ParticleSystem, ContinuousParticleSystem, ExplosionParticleSystem
Successful tests return true in the console.


Contents
A list of the installed files, along with their short descriptions can be found at ../../../../lfs/view/7.5/chapter06/udev.html#contents-udev.
The following is some additional content information.
In 2012, the Udev code distribution was merged with systemd. Systemd is a set of programs that replace the SysVInit package used by LFS and is much more complex. It is not compatible with the LFS bootscripts and has many problems and few advantages for most LFS users.
The procedures below extract libraries and programs from the systemd sources that could not be built in LFS due to library dependency issues.
Unlike any other package in the BLFS book, there is no set version of systemd specified to download. Several version updates to LFS and BLFS means there are probably many different versions of Udev on the platforms that BLFS is being built upon. Therefore, you should download and use the version of systemd your computer currently uses. The BLFS team has no experience updating (or reverting to an older version) the Udev programs “on the fly.” To discover the version of Udev your computer currently uses, issue /sbin/udevadm --version.
This package is known to build and work properly using an LFS-7.5 platform.
Download (HTTP): http://www.freedesktop.org/wiki/Software/systemd/
Download size: ~1.3 MB
Estimated disk space required: ~16 MB
Estimated build time: ~0.1 SBU
http://anduin.linuxfromscratch.org/sources/other/ (match the udev-lfs-???.tar.bz2 tarball version to the systemd version used in LFS). GLib-2.38.2 (for the gudev library), Gperf-3.0.4 (for keymap), and gobject-introspection-1.38.0 (for gir-data, needed for Gnome)
pciutils-3.2.1 and usbutils-007
User Notes: http://wiki.linuxfromscratch.org/blfs/wiki/udev-extras
First, put the custom LFS files in place:
UDEV=<version> tar -xf ../udev-lfs-$UDEV.tar.bz2
For udev-lfs-197-2.tar.bz2, there is a minor error in the Makefile. For that version, run:
sed -i -e '/samsung-9/d' udev-lfs-197-2/makefile-incl.keymap
Starting with systemd-206, the keymap capabilities are built into the udev procedures initial installation in LFS. These procedures only apply to udev versions before 206.
Support for special keys for many laptops is provided by the keymap program and supporting files. If the keymap capability is desired, use:
make -f udev-lfs-$UDEV/Makefile.lfs keymap
To install keymap
and its associated files, issue the following command as the
root
user:
make -f udev-lfs-$UDEV/Makefile.lfs install-keymap
To build the libgudev-1.0 library and interface files, run:
make -f udev-lfs-$UDEV/Makefile.lfs gudev
Install the gudev
library, run, as
the root
user:
make -f udev-lfs-$UDEV/Makefile.lfs install-gudev
To build the gobject-introspection interface (gir) files
for the libgudev-1.0
library, run:
make -f udev-lfs-$UDEV/Makefile.lfs gir-data
Install the gir data, as the root
user:
make -f udev-lfs-$UDEV/Makefile.lfs install-gir-data
There is a shortcut to build and install all of the
udev components at once using
the all and install-all Makefile.lfs
targets. The installation of
this target will overwrite the base LFS udev files and has not
been thoroughly tested at the time of this writing. If using
this procedure, the udev daemon should be stopped before
overwriting the existing udevd
and udev libraries.
A list of the installed files, along with their short descriptions can be found at ../../../../lfs/view/7.5/chapter06/udev.html#contents-udev.
The following is some additional content information.
Last updated on 2014-02-19 02:11:12 -0800


We want to build THE church, not OUR church
Many people ask us what does the Resort mean. The name “THE RESORT” was chosen to describe the lifestyle of a Christian who is constantly living in daily relationship with Jesus. Jesus Christ is our Resort, or as the bible describes in Psalm 91, he is our refuge. When you make Jesus Christ the Resort of your life, you begin to experience his refreshing and rest, no matter what your circumstances. The Resort as a church is dedicated to teaching and building Christians to become aware of the fact that they are SONS and DAUGHTERS of God. With this privilege of being Gods children we have received an inheritance and are heirs of the Kingdom through his son Jesus Christ.
This Kingdom includes experiencing not just the love of God but also the POWER of God, in our daily lives. The Resort originally started as a dream that God put inside of the heart of our head Pastor Andrew Segura. After living in the Philippines, Andrew returned home to Fresno, CA. with a burning desire to see the kingdom of God spread like wildfire here at home in the U.S. He desired to see a genuine, authentic, raw expression of Gods heart be released into the Earth. The steps were set in place to form a non-profit Ministry called ASM which stood for Andrew Segura Ministries. On January 12th, 2016 the State of California recognized ASM as an official incorporated Non-Profit. The Dream had begun.
The first meetings of ASM began as bible studies held on Thursday nights in the homes of friends. The meetings began growing so rapidly that the Ministry changed three locations in four months as the number of people outgrew each home. It was at this time that God led ASM to host their meetings at the Falls Event Center In Fresno, ca. After one year a team of volunteers had gathered around Andrew and then God spoke that ASM would change its name to “The Resort”.
Yet Andrew and the team desired that the Resort wouldn’t just be another church. They began speaking the phrase, “We want to build THE church, not OUR church.” The aim was Keeping the heart and vision focused on building the KINGDOM OF GOD instead of any location, with a heavy emphasis on evangelism and the KINGDOM MINDSET and KINGDOM PRINCIPLES expanding beyond the four walls.
We believe that the God of the bible is the one and only true god. He is the creator of all things, and because He is eternal and self-existent was not created. He described himself as ‘I AM.” He is omnipotent, all-powerful, perfectly holy, the only one capable of exercising perfect justice, completely truthful, and full of love.

We believe the bible is the only source of doctrine for the Christian faith, and is inspired by the Holy Spirit. It is Composed of 66 books, divided into an old and new testament. The Bible as a document is infallible, inerrant, and authoritative. It is to be read daily by Christians as a standard practice of our faith.
We believe the one and only begotten Son of God (John 3:16) is the Lord Jesus Christ. He was born of the virgin, Mary, and conceived of the Holy Spirit. He is fully God and fully man.  He lived a sinless life and was sent to the Earth to establish the Kingdom of God, destroy the works of the devil, and bring salvation to all people. He was crucified on a cross for our sins, died, was buried, and rose from the dead on the third day. Through this resurrection, he gained authority over death, hell, and the grave. After this he ascended into heaven, where he is now seated at the right hand of the throne of God. In John 14:6 Jesus said, “I am the way, the truth, and the life. No one comes to the Father except through me.”
In the book of genesis, God originally created man to walk in perfect relationship with him. The first man was named Adam, and was created in Gods image, without sin to separate him from knowing and enjoying God. In Genesis chapter three, Adam and his wife sinned against god, and willingly and knowingly fell from their created intention. Because of this all of humankind and creation experience the negative consequences of sin, including sickness and disease, guilt, shame, death, and judgement. Salvation
Salvation is the gift of God’s Grace, and only occurs through faith in the work of Jesus Christ on the cross. It is available to anyone who repents of their sins, and decides to confess with their mouth and believe in their heart that Jesus Christ is their Savior and Lord.
The holy spirit is God and regenerates the life of a Christian. He acts as our guide, friend, teacher, comforter, helper, seal of promise, counselor, and advocate. Jesus said the Holy Spirit is the revealer of all truth. He is also the source of conviction in a Christian’s life.
At conversion God seals every believer with the Holy Spirit, who now guides that believer’s life through the process of Sanctification. The baptism of the Holy Spirit as described in the book of acts, is still poured out on believers to empower them to act as witnesses.
The gifts of the Holy Spirit that we see exercised in the Scriptures have not ceased with the death of the last Apostle or the closing of the New Testament canon. They are available today and are to be eagerly desired and practiced in submission to the Spirit speaking through the Scriptures
Freedom is now available to all Christian through the finished work of Christ on the cross. The victory Jesus achieved has resulted in the defeat of all satanic and demonic powers, and stripped them of all rights of authority. A Christian, walking in salvation can now live free of sin, free of sickness and disease, and free from all other lies and activities of the enemy.
The Church is not a religious institution or denomination, neither is it a building or location. The Church is composed of people who have confessed by faith to be followers of Jesus Christ and his gospel. The Church is Gods governing body and the extension of his heavenly kingdom on Earth. The Church exists to worship and glorify God as Father, Son and Holy Spirit. The duty of the church is to advance the kingdom of God on Earth. This is done through making disciples, preaching and teaching the word of God and the good news of the gospel, exercising authority over the powers of hell, demonstration of the love and power of god, baptism, communion, church planting, and evangelism.
We await the future, visible, physical, glorious return of Jesus Christ for his church. At this time the consummation of all things will occur.  Only those who turn from sin and to Jesus in faith and repentance will be raised to eternal reward. Those who do not turn from sin and to Jesus will be raised to eternal punishment. The final judgment will determine the eternal status of both the believers and the unbelievers, determined by their relationship to Jesus Christ. We affirm with the Bible the final state of the new heavens and the new earth.
The heartbeat of our missions teams is to see the love and power of Jesus spread all across this Earth.
We are dedicated to local and Global missions.


My name is Ash and I joined Dev Academy because I wanted to break out of my previous lines of work and enter an industry that put me out of my comfort zone, that enables me to create, and will let me grow within an ever-changing industry.
Having worked in different areas, with varying paces, I found myself always playing around with code in different forms, be it, robotics from Sminks Lab, activities during Hour of Code, or playing around with other users blog templates while customizing my tumblr blog.


WITNESS LIST State, Federal & International Relations Committee March 6, 2001-8:00A HB 1019 For: Saenz, L. Arnold (Jim Wells County Judge) Serna, Serapio (Tejano Roots Board) Villanueva, Javier (Tejano R.O.O.T.S., Inc.) Registering, but not testifying: For: Velasquez, Sally (Hispanic Contractors Assoc. of TX, City of Eagle Pass) HCR 79 Registering, but not testifying: For: Smith, Terral (El Paso Chamber of Commerce) Velasquez, Sally (Webb, Willacy, and Zapata Counties; City of Eagle Pass) HCR 85 For: Harrison, Rob (Center for Transportation Research, University of Texas) Registering, but not testifying: For: Gadbois, Glenn (Texas Citizen Fund) Smith, Terral (El Paso Chamber of Commerce) Velasquez, Sally (Webb, Willacy, and Zapata Counties; the City of Eagle Pass) International Business/Tourism Registering, but not testifying: On: Richards, Gene (Texas Department of Economic Development) International Relations On: Bastarrachea, Julio (State of Texas-Mexico Office) Cuellar, Henry (Texas Secretary of State Office) International Tourism On: Moseley, Jeff (Texas Department of Economic Development)


Toggle navigation
Club99love API Documentation
Classes
Namespaces
Interfaces
Traits
Index
Search
Classes
Address
BaseModel
Club99
Inspire
Kernel
Coupon
Event
Handler
Feature
Fee
GiftCard
AffiliatesController
ClassificationController
CouponsController
DashboardController
DatatablesController
FeaturesController
FeesController
InvoicesController
MenusController
NotificationsController
PackagesController
PagesController
ProductsController
RolesController
SendersController
SettingsController
ShipmentsController
UsersController
AuthController
PasswordController
Controller
FrontendController
MemberController
DashboardController
DatatablesController
InvoicesController
NotificationsController
ProfileController
SendersController
ShipmentsController
ShopController
SubscriptionController
Kernel
ActivateUser
Admin
Authenticate
EncryptCookies
ProfileCompleted
RedirectIfAuthenticated
RedirectSubscription
Subscribed
VerifyCsrfToken
FeatureRequest
MenuRequest
PackageRequest
PageRequest
ProfileRequest
Request
RolesRequest
SettingsRequest
UserRequest
Invoice
Item
Job
Menu
OtherCharge
Package
Page
PnP
Product
AppServiceProvider
AuthServiceProvider
EventServiceProvider
RouteServiceProvider
Retailer
Role
Setting
Shipment
ShipmentDeliveryDetail
StorePayment
Subscription
Tax
User