To Morning:
September 30th, 2009
Now you see
you and I after all
this time-
I have strength to go my own way-
walk away and never look back
I will find you if not in the next life
-I would work myself to death if I believed that-
So I’ll be on my way
I will be there
the sun will rise and
you will be awake
you will be awake
stirred not by moonlight
-nor by foggy dreams
No,- sunlight!
No,- daybreak!
awful daylight morning
all alone or still dreaming
DID YOU CATCH THAT?
If it were a sickness
I would die trying to
be anything but paper words
-[people's uniforms from foreign wars
and dollar bills]


gevent is a concurrency library based around libev. It provides a clean API for a variety of concurrency and network related tasks.
The structure of this tutorial assumes an intermediate level knowledge of Python but not much else. No knowledge of concurrency is expected. The goal is to give you the tools you need to get going with gevent, help you tame your existing concurrency problems and start writing asynchronous applications today.
In chronological order of contribution: Stephen Diehl Jérémy Bethmont sww Bruno Bigras David Ripton Travis Cline Boris Feld youngsterxyf Eddie Hebert Alexis Metaireau Daniel Velkov
Also thanks to Denis Bilenko for writing gevent and guidance in constructing this tutorial.
This is a collaborative document published under MIT license. Have something to add? See a typo? Fork and issue a pull request Github. Any and all contributions are welcome.
This page is also available in Japanese.
The primary pattern used in gevent is the Greenlet, a lightweight coroutine provided to Python as a C extension module. Greenlets all run inside of the OS process for the main program but are scheduled cooperatively.
Only one greenlet is ever running at any given time.
This differs from any of the real parallelism constructs provided by
multiprocessing
or threading
libraries which do spin processes
and POSIX threads which are scheduled by the operating system and
are truly parallel.
The core idea of concurrency is that a larger task can be broken down into a collection of subtasks which are scheduled to run simultaneously or asynchronously, instead of one at a time or synchronously. A switch between the two subtasks is known as a context switch.
A context switch in gevent is done through yielding. In this case
example we have two contexts which yield to each other through invoking
gevent.sleep(0)
.
import gevent
def foo():
print('Running in foo')
gevent.sleep(0)
print('Explicit context switch to foo again')
def bar():
print('Explicit context to bar')
gevent.sleep(0)
print('Implicit context switch back to bar')
gevent.joinall([
gevent.spawn(foo),
gevent.spawn(bar),
])
Running in foo
Explicit context to bar
Explicit context switch to foo again
Implicit context switch back to bar
It is illuminating to visualize the control flow of the program or walk through it with a debugger to see the context switches as they occur.
The real power of gevent comes when we use it for network and IO bound functions which can be cooperatively scheduled. Gevent has taken care of all the details to ensure that your network libraries will implicitly yield their greenlet contexts whenever possible. I cannot stress enough what a powerful idiom this is. But maybe an example will illustrate.
In this case the select()
function is normally a blocking
call that polls on various file descriptors.
import time
import gevent
from gevent import select
start = time.time()
tic = lambda: 'at %1.1f seconds' % (time.time() - start)
def gr1():
# Busy waits for a second, but we don't want to stick around...
print('Started Polling: %s' % tic())
select.select([], [], [], 2)
print('Ended Polling: %s' % tic())
def gr2():
# Busy waits for a second, but we don't want to stick around...
print('Started Polling: %s' % tic())
select.select([], [], [], 2)
print('Ended Polling: %s' % tic())
def gr3():
print("Hey lets do some stuff while the greenlets poll, %s" % tic())
gevent.sleep(1)
gevent.joinall([
gevent.spawn(gr1),
gevent.spawn(gr2),
gevent.spawn(gr3),
])
Started Polling: at 0.0 seconds
Started Polling: at 0.0 seconds
Hey lets do some stuff while the greenlets poll, at 0.0 seconds
Ended Polling: at 2.0 seconds
Ended Polling: at 2.0 seconds
Another somewhat synthetic example defines a task
function
which is non-deterministic
(i.e. its output is not guaranteed to give the same result for
the same inputs). In this case the side effect of running the
function is that the task pauses its execution for a random
number of seconds.
import gevent
import random
def task(pid):
"""
Some non-deterministic task
"""
gevent.sleep(random.randint(0,2)*0.001)
print('Task %s done' % pid)
def synchronous():
for i in range(1,10):
task(i)
def asynchronous():
threads = [gevent.spawn(task, i) for i in xrange(10)]
gevent.joinall(threads)
print('Synchronous:')
synchronous()
print('Asynchronous:')
asynchronous()
Synchronous:
Task 1 done
Task 2 done
Task 3 done
Task 4 done
Task 5 done
Task 6 done
Task 7 done
Task 8 done
Task 9 done
Asynchronous:
Task 3 done
Task 7 done
Task 2 done
Task 6 done
Task 5 done
Task 4 done
Task 0 done
Task 1 done
Task 8 done
Task 9 done
In the synchronous case all the tasks are run sequentially, which results in the main programming blocking ( i.e. pausing the execution of the main program ) while each task executes.
The important parts of the program are the
gevent.spawn
which wraps up the given function
inside of a Greenlet thread. The list of initialized greenlets
are stored in the array threads
which is passed to
the gevent.joinall
function which blocks the current
program to run all the given greenlets. The execution will step
forward only when all the greenlets terminate.
The important fact to notice is that the order of execution in the async case is essentially random and that the total execution time in the async case is much less than the sync case. In fact the maximum time for the synchronous case to complete is when each tasks pauses for 0.002 seconds resulting in a 0.02 seconds for the whole queue. In the async case the maximum runtime is roughly 0.002 seconds since none of the tasks block the execution of the others.
In a more common use case, asynchronously fetching data from a server,
the runtime of fetch()
will differ between
requests, depending on the load on the remote server at the time of the request.
import gevent.monkey
gevent.monkey.patch_socket()
import gevent
import urllib2
import simplejson as json
def fetch(pid):
response = urllib2.urlopen('http://json-time.appspot.com/time.json')
result = response.read()
json_result = json.loads(result)
datetime = json_result['datetime']
print('Process %s: %s' % (pid, datetime))
return json_result['datetime']
def synchronous():
for i in range(1,10):
fetch(i)
def asynchronous():
threads = []
for i in range(1,10):
threads.append(gevent.spawn(fetch, i))
gevent.joinall(threads)
print('Synchronous:')
synchronous()
print('Asynchronous:')
asynchronous()
As mentioned previously, greenlets are deterministic. Given the same configuration of greenlets and the same set of inputs, they always produce the same output. For example, let's spread a task across a multiprocessing pool and compare its results to the one of a gevent pool.
import time
def echo(i):
time.sleep(0.001)
return i
# Non Deterministic Process Pool
from multiprocessing.pool import Pool
p = Pool(10)
run1 = [a for a in p.imap_unordered(echo, xrange(10))]
run2 = [a for a in p.imap_unordered(echo, xrange(10))]
run3 = [a for a in p.imap_unordered(echo, xrange(10))]
run4 = [a for a in p.imap_unordered(echo, xrange(10))]
print(run1 == run2 == run3 == run4)
# Deterministic Gevent Pool
from gevent.pool import Pool
p = Pool(10)
run1 = [a for a in p.imap_unordered(echo, xrange(10))]
run2 = [a for a in p.imap_unordered(echo, xrange(10))]
run3 = [a for a in p.imap_unordered(echo, xrange(10))]
run4 = [a for a in p.imap_unordered(echo, xrange(10))]
print(run1 == run2 == run3 == run4)
False
True
Even though gevent is normally deterministic, sources of non-determinism can creep into your program when you begin to interact with outside services such as sockets and files. Thus even though green threads are a form of "deterministic concurrency", they still can experience some of the same problems that POSIX threads and processes experience.
The perennial problem involved with concurrency is known as a race condition. Simply put, a race condition occurs when two concurrent threads / processes depend on some shared resource but also attempt to modify this value. This results in resources which values become time-dependent on the execution order. This is a problem, and in general one should very much try to avoid race conditions since they result in a globally non-deterministic program behavior.
The best approach to this is to simply avoid all global state at all times. Global state and import-time side effects will always come back to bite you!
gevent provides a few wrappers around Greenlet initialization. Some of the most common patterns are:
import gevent
from gevent import Greenlet
def foo(message, n):
"""
Each thread will be passed the message, and n arguments
in its initialization.
"""
gevent.sleep(n)
print(message)
# Initialize a new Greenlet instance running the named function
# foo
thread1 = Greenlet.spawn(foo, "Hello", 1)
# Wrapper for creating and running a new Greenlet from the named
# function foo, with the passed arguments
thread2 = gevent.spawn(foo, "I live!", 2)
# Lambda expressions
thread3 = gevent.spawn(lambda x: (x+1), 2)
threads = [thread1, thread2, thread3]
# Block until all threads complete.
gevent.joinall(threads)
Hello
I live!
In addition to using the base Greenlet class, you may also subclass
Greenlet class and override the _run
method.
import gevent
from gevent import Greenlet
class MyGreenlet(Greenlet):
def __init__(self, message, n):
Greenlet.__init__(self)
self.message = message
self.n = n
def _run(self):
print(self.message)
gevent.sleep(self.n)
g = MyGreenlet("Hi there!", 3)
g.start()
g.join()
Hi there!
Like any other segment of code, Greenlets can fail in various ways. A greenlet may fail to throw an exception, fail to halt or consume too many system resources.
The internal state of a greenlet is generally a time-dependent parameter. There are a number of flags on greenlets which let you monitor the state of the thread:
started
-- Boolean, indicates whether the Greenlet has been startedready()
-- Boolean, indicates whether the Greenlet has haltedsuccessful()
-- Boolean, indicates whether the Greenlet has halted and not thrown an exceptionvalue
-- arbitrary, the value returned by the Greenletexception
-- exception, uncaught exception instance thrown inside the greenlet
import gevent
def win():
return 'You win!'
def fail():
raise Exception('You fail at failing.')
winner = gevent.spawn(win)
loser = gevent.spawn(fail)
print(winner.started) # True
print(loser.started) # True
# Exceptions raised in the Greenlet, stay inside the Greenlet.
try:
gevent.joinall([winner, loser])
except Exception as e:
print('This will never be reached')
print(winner.value) # 'You win!'
print(loser.value) # None
print(winner.ready()) # True
print(loser.ready()) # True
print(winner.successful()) # True
print(loser.successful()) # False
# The exception raised in fail, will not propogate outside the
# greenlet. A stack trace will be printed to stdout but it
# will not unwind the stack of the parent.
print(loser.exception)
# It is possible though to raise the exception again outside
# raise loser.exception
# or with
# loser.get()
True
True
You win!
None
True
True
True
False
You fail at failing.
Greenlets that fail to yield when the main program receives a SIGQUIT may hold the program's execution longer than expected. This results in so called "zombie processes" which need to be killed from outside of the Python interpreter.
A common pattern is to listen SIGQUIT events on the main program
and to invoke gevent.shutdown
before exit.
import gevent
import signal
def run_forever():
gevent.sleep(1000)
if __name__ == '__main__':
gevent.signal(signal.SIGQUIT, gevent.shutdown)
thread = gevent.spawn(run_forever)
thread.join()
Timeouts are a constraint on the runtime of a block of code or a Greenlet.
import gevent
from gevent import Timeout
seconds = 10
timeout = Timeout(seconds)
timeout.start()
def wait():
gevent.sleep(10)
try:
gevent.spawn(wait).join()
except Timeout:
print('Could not complete')
They can also be used with a context manager, in a with
statement.
import gevent
from gevent import Timeout
time_to_wait = 5 # seconds
class TooLong(Exception):
pass
with Timeout(time_to_wait, TooLong):
gevent.sleep(10)
In addition, gevent also provides timeout arguments for a variety of Greenlet and data stucture related calls. For example:
import gevent
from gevent import Timeout
def wait():
gevent.sleep(2)
timer = Timeout(1).start()
thread1 = gevent.spawn(wait)
try:
thread1.join(timeout=timer)
except Timeout:
print('Thread 1 timed out')
# --
timer = Timeout.start_new(1)
thread2 = gevent.spawn(wait)
try:
thread2.get(timeout=timer)
except Timeout:
print('Thread 2 timed out')
# --
try:
gevent.with_timeout(1, wait)
except Timeout:
print('Thread 3 timed out')
Thread 1 timed out
Thread 2 timed out
Thread 3 timed out
Alas we come to dark corners of Gevent. I've avoided mentioning
monkey patching up until now to try and motivate the powerful
coroutine patterns, but the time has come to discuss the dark arts
of monkey-patching. If you noticed above we invoked the command
monkey.patch_socket()
. This is a purely side-effectful command to
modify the standard library's socket library.
import socket
print(socket.socket)
print("After monkey patch")
from gevent import monkey
monkey.patch_socket()
print(socket.socket)
import select
print(select.select)
monkey.patch_select()
print("After monkey patch")
print(select.select)
class 'socket.socket'
After monkey patch
class 'gevent.socket.socket'
built-in function select
After monkey patch
function select at 0x1924de8
Python's runtime allows for most objects to be modified at runtime
including modules, classes, and even functions. This is generally an
astoudingly bad idea since it creates an "implicit side-effect" that is
most often extremely difficult to debug if problems occur, nevertheless
in extreme situations where a library needs to alter the fundamental
behavior of Python itself monkey patches can be used. In this case gevent
is capable of patching most of the blocking system calls in the standard
library including those in socket
, ssl
, threading
and
select
modules to instead behave cooperatively.
For example, the Redis python bindings normally uses regular tcp
sockets to communicate with the redis-server
instance. Simply
by invoking gevent.monkey.patch_all()
we can make the redis
bindings schedule requests cooperatively and work with the rest
of our gevent stack.
This lets us integrate libraries that would not normally work with gevent without ever writing a single line of code. While monkey-patching is still evil, in this case it is a "useful evil".
Events are a form of asynchronous communication between Greenlets.
import gevent
from gevent.event import Event
'''
Illustrates the use of events
'''
evt = Event()
def setter():
'''After 3 seconds, wake all threads waiting on the value of evt'''
print('A: Hey wait for me, I have to do something')
gevent.sleep(3)
print("Ok, I'm done")
evt.set()
def waiter():
'''After 3 seconds the get call will unblock'''
print("I'll wait for you")
evt.wait() # blocking
print("It's about time")
def main():
gevent.joinall([
gevent.spawn(setter),
gevent.spawn(waiter),
gevent.spawn(waiter),
gevent.spawn(waiter),
gevent.spawn(waiter),
gevent.spawn(waiter)
])
if __name__ == '__main__': main()
A extension of the Event object is the AsyncResult which allows you to send a value along with the wakeup call. This is sometimes called a future or a deferred, since it holds a reference to a future value that can be set on an arbitrary time schedule.
import gevent
from gevent.event import AsyncResult
a = AsyncResult()
def setter():
"""
After 3 seconds set the result of a.
"""
gevent.sleep(3)
a.set('Hello!')
def waiter():
"""
After 3 seconds the get call will unblock after the setter
puts a value into the AsyncResult.
"""
print(a.get())
gevent.joinall([
gevent.spawn(setter),
gevent.spawn(waiter),
])
Queues are ordered sets of data that have the usual put
/ get
operations but are written in a way such that they can be safely
manipulated across Greenlets.
For example, if one Greenlet grabs an item off of the queue, the same item will not be grabbed by another Greenlet executing simultaneously.
import gevent
from gevent.queue import Queue
tasks = Queue()
def worker(n):
while not tasks.empty():
task = tasks.get()
print('Worker %s got task %s' % (n, task))
gevent.sleep(0)
print('Quitting time!')
def boss():
for i in xrange(1,25):
tasks.put_nowait(i)
gevent.spawn(boss).join()
gevent.joinall([
gevent.spawn(worker, 'steve'),
gevent.spawn(worker, 'john'),
gevent.spawn(worker, 'nancy'),
])
Worker steve got task 1
Worker john got task 2
Worker nancy got task 3
Worker steve got task 4
Worker nancy got task 5
Worker john got task 6
Worker steve got task 7
Worker john got task 8
Worker nancy got task 9
Worker steve got task 10
Worker nancy got task 11
Worker john got task 12
Worker steve got task 13
Worker john got task 14
Worker nancy got task 15
Worker steve got task 16
Worker nancy got task 17
Worker john got task 18
Worker steve got task 19
Worker john got task 20
Worker nancy got task 21
Worker steve got task 22
Worker nancy got task 23
Worker john got task 24
Quitting time!
Quitting time!
Quitting time!
Queues can also block on either put
or get
as the need arises.
Each of the put
and get
operations has a non-blocking
counterpart, put_nowait
and
get_nowait
which will not block, but instead raise
either gevent.queue.Empty
or
gevent.queue.Full
in the operation is not possible.
In this example we have the boss running simultaneously to the
workers and have a restriction on the Queue preventing it from containing
more than three elements. This restriction means that the put
operation will block until there is space on the queue.
Conversely the get
operation will block if there are
no elements on the queue to fetch, it also takes a timeout
argument to allow for the queue to exit with the exception
gevent.queue.Empty
if no work can found within the
time frame of the Timeout.
import gevent
from gevent.queue import Queue, Empty
tasks = Queue(maxsize=3)
def worker(n):
try:
while True:
task = tasks.get(timeout=1) # decrements queue size by 1
print('Worker %s got task %s' % (n, task))
gevent.sleep(0)
except Empty:
print('Quitting time!')
def boss():
"""
Boss will wait to hand out work until a individual worker is
free since the maxsize of the task queue is 3.
"""
for i in xrange(1,10):
tasks.put(i)
print('Assigned all work in iteration 1')
for i in xrange(10,20):
tasks.put(i)
print('Assigned all work in iteration 2')
gevent.joinall([
gevent.spawn(boss),
gevent.spawn(worker, 'steve'),
gevent.spawn(worker, 'john'),
gevent.spawn(worker, 'bob'),
])
Worker steve got task 1
Worker john got task 2
Worker bob got task 3
Worker steve got task 4
Worker bob got task 5
Worker john got task 6
Assigned all work in iteration 1
Worker steve got task 7
Worker john got task 8
Worker bob got task 9
Worker steve got task 10
Worker bob got task 11
Worker john got task 12
Worker steve got task 13
Worker john got task 14
Worker bob got task 15
Worker steve got task 16
Worker bob got task 17
Worker john got task 18
Assigned all work in iteration 2
Worker steve got task 19
Quitting time!
Quitting time!
Quitting time!
A group is a collection of running greenlets which are managed
and scheduled together as group. It also doubles as parallel
dispatcher that mirrors the Python multiprocessing
library.
import gevent
from gevent.pool import Group
def talk(msg):
for i in xrange(3):
print(msg)
g1 = gevent.spawn(talk, 'bar')
g2 = gevent.spawn(talk, 'foo')
g3 = gevent.spawn(talk, 'fizz')
group = Group()
group.add(g1)
group.add(g2)
group.join()
group.add(g3)
group.join()
bar
bar
bar
foo
foo
foo
fizz
fizz
fizz
This is very useful for managing groups of asynchronous tasks.
As mentioned above, Group
also provides an API for dispatching
jobs to grouped greenlets and collecting their results in various
ways.
import gevent
from gevent import getcurrent
from gevent.pool import Group
group = Group()
def hello_from(n):
print('Size of group %s' % len(group))
print('Hello from Greenlet %s' % id(getcurrent()))
group.map(hello_from, xrange(3))
def intensive(n):
gevent.sleep(3 - n)
return 'task', n
print('Ordered')
ogroup = Group()
for i in ogroup.imap(intensive, xrange(3)):
print(i)
print('Unordered')
igroup = Group()
for i in igroup.imap_unordered(intensive, xrange(3)):
print(i)
Size of group 3
Hello from Greenlet 157878268
Size of group 3
Hello from Greenlet 157878828
Size of group 3
Hello from Greenlet 157878908
Ordered
('task', 0)
('task', 1)
('task', 2)
Unordered
('task', 2)
('task', 1)
('task', 0)
A pool is a structure designed for handling dynamic numbers of greenlets which need to be concurrency-limited. This is often desirable in cases where one wants to do many network or IO bound tasks in parallel.
import gevent
from gevent.pool import Pool
pool = Pool(2)
def hello_from(n):
print('Size of pool %s' % len(pool))
pool.map(hello_from, xrange(3))
Size of pool 2
Size of pool 2
Size of pool 1
Often when building gevent driven services one will center the entire service around a pool structure. An example might be a class which polls on various sockets.
from gevent.pool import Pool
class SocketPool(object):
def __init__(self):
self.pool = Pool(1000)
self.pool.start()
def listen(self, socket):
while True:
socket.recv()
def add_handler(self, socket):
if self.pool.full():
raise Exception("At maximum pool size")
else:
self.pool.spawn(self.listen, socket)
def shutdown(self):
self.pool.kill()
A semaphore is a low level synchronization primitive that allows
greenlets to coordinate and limit concurrent access or execution. A
semaphore exposes two methods, acquire
and release
The
difference between the number of times and a semaphore has been
acquired and released is called the bound of the semaphore. If a
semaphore bound reaches 0 it will block until another greenlet
releases its acquisition.
from gevent import sleep
from gevent.pool import Pool
from gevent.coros import BoundedSemaphore
sem = BoundedSemaphore(2)
def worker1(n):
sem.acquire()
print('Worker %i acquired semaphore' % n)
sleep(0)
sem.release()
print('Worker %i released semaphore' % n)
def worker2(n):
with sem:
print('Worker %i acquired semaphore' % n)
sleep(0)
print('Worker %i released semaphore' % n)
pool = Pool()
pool.map(worker1, xrange(0,2))
pool.map(worker2, xrange(3,6))
Worker 0 acquired semaphore
Worker 1 acquired semaphore
Worker 0 released semaphore
Worker 1 released semaphore
Worker 3 acquired semaphore
Worker 4 acquired semaphore
Worker 3 released semaphore
Worker 4 released semaphore
Worker 5 acquired semaphore
Worker 5 released semaphore
A semaphore with bound of 1 is known as a Lock. it provides exclusive execution to one greenlet. They are often used to ensure that resources are only in use at one time in the context of a program.
Gevent also allows you to specify data which is local to the
greenlet context. Internally, this is implemented as a global
lookup which addresses a private namespace keyed by the
greenlet's getcurrent()
value.
import gevent
from gevent.local import local
stash = local()
def f1():
stash.x = 1
print(stash.x)
def f2():
stash.y = 2
print(stash.y)
try:
stash.x
except AttributeError:
print("x is not local to f2")
g1 = gevent.spawn(f1)
g2 = gevent.spawn(f2)
gevent.joinall([g1, g2])
1
2
x is not local to f2
Many web framework thats integrate with gevent store HTTP session objects inside of gevent thread locals. For example using the Werkzeug utility library and its proxy object we can create Flask style request objects.
from gevent.local import local
from werkzeug.local import LocalProxy
from werkzeug.wrappers import Request
from contextlib import contextmanager
from gevent.wsgi import WSGIServer
_requests = local()
request = LocalProxy(lambda: _requests.request)
@contextmanager
def sessionmanager(environ):
_requests.request = Request(environ)
yield
_requests.request = None
def logic():
return "Hello " + request.remote_addr
def application(environ, start_response):
status = '200 OK'
with sessionmanager(environ):
body = logic()
headers = [
('Content-Type', 'text/html')
]
start_response(status, headers)
return [body]
WSGIServer(('', 8000), application).serve_forever()
Flask's system is a bit more sophisticated than this example, but the idea of using thread locals as local session storage is nonetheless the same.
As of gevent 1.0, gevent.subprocess
-- a patched version of Python's
subprocess
module -- has been added. It supports cooperative waiting on
subprocesses.
import gevent
from gevent.subprocess import Popen, PIPE
def cron():
while True:
print("cron")
gevent.sleep(0.2)
g = gevent.spawn(cron)
sub = Popen(['sleep 1; uname'], stdout=PIPE, shell=True)
out, err = sub.communicate()
g.kill()
print(out.rstrip())
cron
cron
cron
cron
cron
Linux
Many people also want to use gevent
and multiprocessing
together. One of
the most obvious challenges is that inter-process communication provided by
multiprocessing
is not cooperative by default. Since
multiprocessing.Connection
-based objects (such as Pipe
) expose their
underlying file descriptors, gevent.socket.wait_read
and wait_write
can
be used to cooperatively wait for ready-to-read/ready-to-write events before
actually reading/writing:
import gevent
from multiprocessing import Process, Pipe
from gevent.socket import wait_read, wait_write
# To Process
a, b = Pipe()
# From Process
c, d = Pipe()
def relay():
for i in xrange(10):
msg = b.recv()
c.send(msg + " in " + str(i))
def put_msg():
for i in xrange(10):
wait_write(a.fileno())
a.send('hi')
def get_msg():
for i in xrange(10):
wait_read(d.fileno())
print(d.recv())
if __name__ == '__main__':
proc = Process(target=relay)
proc.start()
g1 = gevent.spawn(get_msg)
g2 = gevent.spawn(put_msg)
gevent.joinall([g1, g2], timeout=1)
Note, however, that the combination of multiprocessing
and gevent brings
along certain OS-dependent pitfalls, among others:
multiprocessing.Process
creation run in both, parent and
child process.a.send()
in put_msg()
above might still block the calling thread
non-cooperatively: a ready-to-write event only ensures that one byte can be
written. The underlying buffer might be full before the attempted write is
complete.wait_write()
/ wait_read()
-based approach as indicated above does
not work on Windows (IOError: 3 is not a socket (files are not supported)
),
because Windows cannot watch pipes for events.The Python package gipc overcomes these
challenges for you in a largely transparent fashion on both, POSIX-compliant and
Windows systems. It provides gevent-aware multiprocessing.Process
-based
child processes and gevent-cooperative inter-process communication based on
pipes.
The actor model is a higher level concurrency model popularized by the language Erlang. In short the main idea is that you have a collection of independent Actors which have an inbox from which they receive messages from other Actors. The main loop inside the Actor iterates through its messages and takes action according to its desired behavior.
Gevent does not have a primitive Actor type, but we can define one very simply using a Queue inside of a subclassed Greenlet.
import gevent
from gevent.queue import Queue
class Actor(gevent.Greenlet):
def __init__(self):
self.inbox = Queue()
gevent.Greenlet.__init__(self)
def receive(self, message):
"""
Define in your subclass.
"""
raise NotImplemented()
def _run(self):
self.running = True
while self.running:
message = self.inbox.get()
self.receive(message)
In a use case:
import gevent
from gevent.queue import Queue
from gevent import Greenlet
class Pinger(Actor):
def receive(self, message):
print(message)
pong.inbox.put('ping')
gevent.sleep(0)
class Ponger(Actor):
def receive(self, message):
print(message)
ping.inbox.put('pong')
gevent.sleep(0)
ping = Pinger()
pong = Ponger()
ping.start()
pong.start()
ping.inbox.put('start')
gevent.joinall([ping, pong])
ZeroMQ is described by its authors as "a socket library that acts as a concurrency framework". It is a very powerful messaging layer for building concurrent and distributed applications.
ZeroMQ provides a variety of socket primitives, the simplest of
which being a Request-Response socket pair. A socket has two
methods of interest send
and recv
, both of which are
normally blocking operations. But this is remedied by a briliant
library by Travis Cline which
uses gevent.socket to poll ZeroMQ sockets in a non-blocking
manner. You can install gevent-zeromq from PyPi via: pip install
gevent-zeromq
# Note: Remember to ``pip install pyzmq gevent_zeromq``
import gevent
from gevent_zeromq import zmq
# Global Context
context = zmq.Context()
def server():
server_socket = context.socket(zmq.REQ)
server_socket.bind("tcp://<IP_ADDRESS>:5000")
for request in range(1,10):
server_socket.send("Hello")
print('Switched to Server for %s' % request)
# Implicit context switch occurs here
server_socket.recv()
def client():
client_socket = context.socket(zmq.REP)
client_socket.connect("tcp://<IP_ADDRESS>:5000")
for request in range(1,10):
client_socket.recv()
print('Switched to Client for %s' % request)
# Implicit context switch occurs here
client_socket.send("World")
publisher = gevent.spawn(server)
client = gevent.spawn(client)
gevent.joinall([publisher, client])
Switched to Server for 1
Switched to Client for 1
Switched to Server for 2
Switched to Client for 2
Switched to Server for 3
Switched to Client for 3
Switched to Server for 4
Switched to Client for 4
Switched to Server for 5
Switched to Client for 5
Switched to Server for 6
Switched to Client for 6
Switched to Server for 7
Switched to Client for 7
Switched to Server for 8
Switched to Client for 8
Switched to Server for 9
Switched to Client for 9
# On Unix: Access with ``$ nc <IP_ADDRESS> 5000``
# On Window: Access with ``$ telnet <IP_ADDRESS> 5000``
from gevent.server import StreamServer
def handle(socket, address):
socket.send("Hello from a telnet!\n")
for i in range(5):
socket.send(str(i) + '\n')
socket.close()
server = StreamServer(('<IP_ADDRESS>', 5000), handle)
server.serve_forever()
Gevent provides two WSGI servers for serving content over HTTP.
Henceforth called wsgi
and pywsgi
:
In earlier versions of gevent before 1.0.x, gevent used libevent
instead of libev. Libevent included a fast HTTP server which was
used by gevent's wsgi
server.
In gevent 1.0.x there is no http server included. Instead
gevent.wsgi
is now an alias for the pure Python server in
gevent.pywsgi
.
If you are using gevent 1.0.x, this section does not apply
For those familiar with streaming HTTP services, the core idea is that in the headers we do not specify a length of the content. We instead hold the connection open and flush chunks down the pipe, prefixing each with a hex digit indicating the length of the chunk. The stream is closed when a size zero chunk is sent.
HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked
8
<p>Hello
9
World</p>
0
The above HTTP connection could not be created in wsgi because streaming is not supported. It would instead have to buffered.
from gevent.wsgi import WSGIServer
def application(environ, start_response):
status = '200 OK'
body = '<p>Hello World</p>'
headers = [
('Content-Type', 'text/html')
]
start_response(status, headers)
return [body]
WSGIServer(('', 8000), application).serve_forever()
Using pywsgi we can however write our handler as a generator and yield the result chunk by chunk.
from gevent.pywsgi import WSGIServer
def application(environ, start_response):
status = '200 OK'
headers = [
('Content-Type', 'text/html')
]
start_response(status, headers)
yield "<p>Hello"
yield "World</p>"
WSGIServer(('', 8000), application).serve_forever()
But regardless, performance on Gevent servers is phenomenal compared to other Python servers. libev is a very vetted technology and its derivative servers are known to perform well at scale.
To benchmark, try Apache Benchmark ab
or see this
Benchmark of Python WSGI Servers
for comparison with other servers.
$ ab -n 10000 -c 100 http://<IP_ADDRESS>:8000/
import gevent
from gevent.queue import Queue, Empty
from gevent.pywsgi import WSGIServer
import simplejson as json
data_source = Queue()
def producer():
while True:
data_source.put_nowait('Hello World')
gevent.sleep(1)
def ajax_endpoint(environ, start_response):
status = '200 OK'
headers = [
('Content-Type', 'application/json')
]
start_response(status, headers)
while True:
try:
datum = data_source.get(timeout=5)
yield json.dumps(datum) + '\n'
except Empty:
pass
gevent.spawn(producer)
WSGIServer(('', 8000), ajax_endpoint).serve_forever()
Websocket example which requires gevent-websocket.
# Simple gevent-websocket server
import json
import random
from gevent import pywsgi, sleep
from geventwebsocket.handler import WebSocketHandler
class WebSocketApp(object):
'''Send random data to the websocket'''
def __call__(self, environ, start_response):
ws = environ['wsgi.websocket']
x = 0
while True:
data = json.dumps({'x': x, 'y': random.randint(1, 5)})
ws.send(data)
x += 1
sleep(0.5)
server = pywsgi.WSGIServer(("", 10000), WebSocketApp(),
handler_class=WebSocketHandler)
server.serve_forever()
HTML Page:
<html>
<head>
<title>Minimal websocket application</title>
<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript">
$(function() {
// Open up a connection to our server
var ws = new WebSocket("ws://localhost:10000/");
// What do we do when we get a message?
ws.onmessage = function(evt) {
$("#placeholder").append('<p>' + evt.data + '</p>')
}
// Just update our conn_status field with the connection status
ws.onopen = function(evt) {
$('#conn_status').html('<b>Connected</b>');
}
ws.onerror = function(evt) {
$('#conn_status').html('<b>Error</b>');
}
ws.onclose = function(evt) {
$('#conn_status').html('<b>Closed</b>');
}
});
</script>
</head>
<body>
<h1>WebSocket Example</h1>
<div id="conn_status">Not Connected</div>
<div id="placeholder" style="width:600px;height:300px;"></div>
</body>
</html>
The final motivating example, a realtime chat room. This example requires Flask ( but not neccesarily so, you could use Django, Pyramid, etc ). The corresponding Javascript and HTML files can be found here.
# Micro gevent chatroom.
# ----------------------
from flask import Flask, render_template, request
from gevent import queue
from gevent.pywsgi import WSGIServer
import simplejson as json
app = Flask(__name__)
app.debug = True
rooms = {
'topic1': Room(),
'topic2': Room(),
}
users = {}
class Room(object):
def __init__(self):
self.users = set()
self.messages = []
def backlog(self, size=25):
return self.messages[-size:]
def subscribe(self, user):
self.users.add(user)
def add(self, message):
for user in self.users:
print(user)
user.queue.put_nowait(message)
self.messages.append(message)
class User(object):
def __init__(self):
self.queue = queue.Queue()
@app.route('/')
def choose_name():
return render_template('choose.html')
@app.route('/<uid>')
def main(uid):
return render_template('main.html',
uid=uid,
rooms=rooms.keys()
)
@app.route('/<room>/<uid>')
def join(room, uid):
user = users.get(uid, None)
if not user:
users[uid] = user = User()
active_room = rooms[room]
active_room.subscribe(user)
print('subscribe %s %s' % (active_room, user))
messages = active_room.backlog()
return render_template('room.html',
room=room, uid=uid, messages=messages)
@app.route("/put/<room>/<uid>", methods=["POST"])
def put(room, uid):
user = users[uid]
room = rooms[room]
message = request.form['message']
room.add(':'.join([uid, message]))
return ''
@app.route("/poll/<uid>", methods=["POST"])
def poll(uid):
try:
msg = users[uid].queue.get(timeout=10)
except queue.Empty:
msg = []
return json.dumps(msg)
if __name__ == "__main__":
http = WSGIServer(('', 5000), app)
http.serve_forever()


---
layout: post
title: Jeanloup Sieff Book - Get 'um While They Last
tags:
- Black and White
- books
- fashion
- General Photography
- inspiration
- Jeanloup Sieff
- Site News
status: publish
type: post
published: true
meta:
aktt_notify_twitter: "yes"
_edit_last: "2"
_edit_lock: "1282583266"
ghostpool_post_template: Default
ghostpool_link: Full Size Image/Video
aktt_tweeted: "1"
_wp_old_slug: ""
dsq_thread_id: "381056082"
---
Some of you probably know that Jeanloup Sieff is one of my inspirations and has been since I was a young photographer in the 80's. His work spans decades and transcends his label as a "fashion photographer". Except for some of the well know iconic people that are in his images that for ever set a time - I feel that his work is as fresh and relevant as it was when it was first made.
I have written quite a bit about him and suggested a book titled Jeanloup Sieff 40 Years of Photography for those interested in seeing this man's work along with a highly engaging read to boot. Well way back when I mentioned this book I had no idea it was so much money nowadays and issued an apology. At the time copies were pushing $500. Well I just happened to look the other day and guess what - there are a few copies available for $50. At 50 bucks this is a must have for anyone that likes photo books and photographer's monographs.
Check it out.
RB


Left Proximal Length
Right Proximal Length
Left Distal Length
Right Distal Length
Actuator Distance
Work mode 1:
Work mode 2:
Work mode 3:
Work mode 4:


{{title}}
Welcome to tab 1
{{title}}
Welcome to tab 2
Wrong Validator
Wrong Validator| Length sould be more than 5


First, an html table with manually expressed structure. Visibility should be coherent (stay correct!).
Next, a script constructed one.


Flagged posts
Review flagged posts and decide what to do.

Allow
Remove


11 Amazon hacks every shopper should know to bag a bargain in the run up to Christmas
With Christmas fast approaching, these tips will make sure you get the most out of your next Amazon shop
by Alice IrvingChristmas is fast approaching and shoppers are on the lookout for deals.
With plenty of offers online, many turn to one of the most popular websites in the world - Amazon .

While there maybe plenty of deals to be had, the cost of your Christmas shop can soon mount up.
But there are ways in which you can snap up amazing deals and save cash.
These top tips will make sure you get the most out of your next Amazon shop.
1. Earn free Amazon vouchers
A website called Swagbucks allows users to complete simple tasks like watching videos and answering polls to win 'SB' points.
SB points can then be cashed in for Amazon vouchers.
If you earn 700 SB in the first 30 days of your free membership Swagbucks will reward you with a £10 bonus.
2. Don't be had - become a price tracking expert
Camelcamelcamel is free Amazon price tracker.
The site monitors millions of Amazon products and sends you an alert when the price drops.
- Create Amazon 'price watches' and receive the notifications via email and Twitter
- View a graph of a specific product's price history (data of over 18 million products has been collected)
- Add the 'Camelizer' extension to your browser to clearly view product data as you shop online so you can make sure that you're getting your chosen product for a good price
The website also has a page dedicated to the biggest price drops in Amazon's history including price drops for LG televisions, iPhones and camera lenses.
Click here to create a free account.
3. Spot potential refunds
An annoying aspect of online shopping is the possibility of late deliveries.
But when your parcel arrives a day or two after it was expected - if Amazon is alerted - you could be compensated for the inconvience.
Make sure you always email the company when you experience late deliveries or are unhappy with the service provided.
You could also use Paribus .

The company also tracks return windows and like Camelcamelcamel, will also monitors product prices.
4. Visit the Amazon Outlet first
If you're after a particular product - have a look for it in the Amazon Outlet section before you consider purchasing a full price product.
The outlet features overstocked items in their original conditions.
Deals have included 78 per cent off computer accessories and 58pc off baby products.
5. Check out Amazon Warehouse deals for a second-hand bargain
If you don't mind buying a used product - have a look at Amazon Warehouse .
Computing and electronic products are often advertised for at least £100 cheaper than their brand new equivalents.
6. Subscribe & Save - and then cancel if you want to
Regular Amazon shoppers can save up to 15pc when receiving five or more subscriptions in a single delivery.
Prime members can get up to 20pc off nappies and baby food when receiving five or more subscriptions in a single delivery.
There's no commitment with the scheme so you can cancel after your first delivery.
Amazon also has a Subscribe & Save Vouchers page where you can get up to 40pc off your first delivery when you set up a subscription for that product (some restrictions apply).
7. Avoid shopping on your phone if you want a discount
Honey is a discount finding browser extension that doesn't work on mobile phone devices.
When shopping on Amazon, Honey will alert you with relevant discount codes once you reach the checkout.
8. Make sure you know EVERYTHING that's included in your Amazon Prime membership
You might know about Amazon Prime's delivery and video benefits but do you know about Prime's other perks?
Current Amazon Prime benefits:
(For eligible Prime products and addresses)
- Unlimited one-day delivery for no extra cost
- Unlimited same-day (evening) delivery for no extra cost
- Delivery upgrades for no extra cost
- Amazon Day : Choose a weekly delivery day for all items you buy throughout the week)
- Unlimited streaming of movies and TV episodes
- Secure unlimited photo storage in Amazon Cloud Drive
- Prime Music : Stream, store, manage and play music anywhere from the cloud
- Kindle Owners Lending Library : Borrow one Kindle book a month for no extra cost
- Kindle First : Early access to download a new book every month at no additional cost from the Kindle First picks
- Prime Wardrobe : Try before you buy - get seven days before you're charged for your purchased clothing item
- Twitch Prime : Twitch.tv users get ad-free viewing on Twitch
- Access to Amazon Pantry (non-members do not have access)
- Prime Early Access : Get 30-minute early access to Lightning Deals on Amazon.co.uk
- Amazon Family : Save 20 per cent on nappies and baby food subscriptions (excluding formula)
- Amazon Household : Share Amazon Prime benefits with another member of your household for no extra charge
For more information about Amazon Prime benefits click here .
9.

10. Sign up for Amazon's free trials - and set reminders to cancel them
Amazon Prime
The Amazon Prime free trial lasts for 30 days.
When the trial ends, membership costs £7.99 per month and you can cancel anytime.
Prime Student
The Prime Student trial lasts for six months.
When the trial ends, the student membership costs £3.99 a month and you can cancel at anytime.
If you want to cancel set an alarm on your phone to remind you to cancel before you get charged.
11. Donate to charity without it costing you a penny
Shopping via smile.amazon.co.uk will donate 0.5pc of an eligible product's sale price to a charity of your choice.


leolu.info
Menu
Home
Your
passion
is within you
Below is how to chase it
Leo: putting thoughts to paper while working in finance
Staying hungry means waking up early, charging forward, and prioritizing
It IS possible to work full-time and pursue your passion
Mission statement, conception, site description


OSCP Like VMs
http://www.abatchy.com/2017/02/oscp-like-vulnhub-vms.html
http://www.brianlinkletter.com/open-source-network-simulators/
https://github.com/sagishahar/lpeworkshop
Vulnhub maybe kinda sorta like OSCP
Kioptrix Level 1
Kioptrix Level 1.1
Kioptrix Level 1.2
Kioptrix Level 1.3
Kioptrix2014
pWnOS v2.0
SickOs 1
SickOS 1.2
Stapler
Tr0ll
Tr0ll2
Vulnix
VulnOSv2
FristiLeaks 1.3
LordOfTheRoot 1.0.1
mrRobot
pwnlab_init
pentesterlabpro vs virtualhackinglabs vs hackthebox.eu vs vulnhub?
virtualhackinglabs.com is probably the closest to what you need for OSCP. if you pay for at least a month, you get a coursebook that is really similar to the PWK coursebook. the differences will actually complement what you learn when you do the PWK course.
i learned a lot about kali linux tools from doing ippSec walkthroughs on hackthebox. most of their boxes are more CTF, but if you get a VIP subscription you have access to all the retired machines and walkthroughs are only available for retired machines. although VHL is most similar to the OSCP lab, you may get more out of doing a lot of ippSec walkthroughs with HTB first.
vulnhub has a mix of CTF and more realistic (?) machines. the big problem with vulnhub boxes is that i haven't found any windows machines. VHL and HTB both have windows boxes. i got a lot of value out of vulnhub walkthroughs, and the best part is that everything about vulnhub is free.
from what i've done with pentesterlabpro, so far it's brilliant. however, it focuses more on web attacks. you could prepare for OSCP without it, imo.
Over The Wire: Bandit
Over The Wire: Natas


Kyiv, Ukraine
Kachalka
Kyiv's answer to Muscle Beach is a Soviet-era gym made from scrap metal.
by SamRIf cramming into an indoor gym using conventional weightlifting machines isn’t your thing, perhaps try working out at Kachalka, whose machines are made from recycled tank chains and various other rusted scrap metal.
In the early ’70s, the Polish gymnast Kasimir Jagelsky and mathematics professor Yuri Kuk decided to create a collective, open-air gym from recycled metal. The scraps, salvaged from old factories and landfills, were ingeniously repurposed to create rowing machines, leg presses, dozens of bench presses, and more.
The name Kachalka is derived from the Ukrainian word kachat, which means “to pump.” Today, the gym remains popular with locals and visitors alike, and is open and free year-round. Enthusiasts maintain the gym, and continue to construct new equipment from whatever they can find.
Know Before You Go
The gym is free to use and is open throughout the year.
Visit Ukraine with Atlas Obscura Trips
Kyiv, Chernobyl, and the Borders of Bessarabia
On this once-in-a-lifetime tour of Ukraine, Transnistria, and Moldova, we'll delve deep into local cultures and traditions, explore unusual underground spaces, and visit an unrecognized republic.
Learn More »
Community Discussion
-
No Comments Yet
Start the discussion. forum Visit our forums.
Sources
- https://abcnews.go.com/International/soviet-era-fitness-strong-kiev/story?id=17573065
- https://www.youtube.com/watch?v=n3QEGI0V0HE
- https://www.spiegel.de/international/zeitgeist/kachalka-soviet-era-fitness-park-still-popular-in-kiev-ukraine-a-863216.html
- https://www.spottedbylocals.com/kyiv/kachalka/


BASE_URL = "http://localhost:8000/"
IMG_DIR = os.path.expanduser("~") + "/donkey_imgs/"
def setup():
""" Create necessary directories """
// Check the mode: recording vs TF driving vs TF driving + recording.
if args["record"]:
we_are_autonomous = False
we_are_recording = True
print("\n------ Ready to record training data ------\n")


Theory of pore-scale transport to enable improved flow batteries
| Source: | University of Illinois College of Engineering |
| Summary: | Redox flow batteries are an emerging technology for electrochemical energy storage that could help enhance the use of power produced by renewable energy resources. Scientists have addressed some of its challenges with a new theory to predict how fluid flow affects the ability of molecules in a flow battery to react at the surfaces of porous electrodes. |
Redox flow batteries are an emerging technology for electrochemical energy storage that could help enhance the use of power produced by renewable energy resources. These power resources are inherently irregular in their supply, which doesn't typically align with demand on the power grid. In principle, redox flow batteries can be designed to have an energy-storage capacity that is independent of its power rating. However, in practice, the ease with which redox-active molecules are transported to electrode surfaces plays an important role in determining their efficiency, the power that is produced or charged and, in some instances, their length of life.
In a new paper, Assistant Professor Kyle Smith addressed these challenges with a new theory to predict how fluid flow affects the ability of molecules in a flow battery to react at the surfaces of porous electrodes. "Modeling the Transient Effects of Pore-Scale Convection and Redox Reactions in the Pseudo-Steady Limit" was published in a focus issue of the Journal of the Electrochemical Society in honor of Illinois' Richard C. Alkire, the Charles J. and Dorothy G. Prizer Chair Emeritus in the Department of Chemical and Biomolecular Engineering, former Vice Chancellor for Research, and former Dean of the Graduate College. Alkire is known world-wide for his expertise in metal deposition and multi-scale simulations from atomic-to-processing scales.
Smith and his PhD student theorized in the research that the rates of reaction at microscopic scales were relevant to the underlying microscopic structure of the electrode material. The results of his model enabled him to predict how molecular transport occurs under so-called transient conditions, where the concentrations of redox-active molecules in the battery's electrolyte change with time.
"We showed that these conditions are particularly relevant to the operation of redox flow batteries, which experience dynamic charge and discharge processes in which electrolyte composition changes with time. This was in contrast to earlier work that had considered such effects primarily from a steady state context where composition is constant in time," said Smith. "The theory we introduced enables the prediction of mass transfer coefficients based on the microscopic pore structure within electrodes that electrolytes are charged and discharged within. Having such capabilities enables us to engineer how such structures should be designed — in other words, how to engineer them."
Smith's finding impacts numerous engineering applications where pore-scale transport is important, including water purification and desalination, catalytic purification of industrial and vehicle exhaust, and transport of reactive minerals and biodegradation of living cells.
This work relates well to Alkire's career research in improving design in engineering through multi-scale simulations. "The overarching goal of this special volume is to address the need for new engineering methods, driven by remarkable discoveries at the scale of molecules, as well as rapid growth in massive data archives. The focus is on developing new design methods for linking behavior at the molecular scale with traditional electrochemical engineering design procedures at the macroscopic scale. The purpose is to embed quality control at the molecular scale into well-engineered products and processes," said Alkire of the focus issue published in his honor.
The paper by Smith and first author, doctoral candidate Md Abdul Hamid, is the only one in the issue published by an Illinois researcher.
make a difference: sponsored opportunity
Story Source:
Materials provided by University of Illinois College of Engineering.
Note: Content may be edited for style and length.
Journal Reference:
- Md Abdul Hamid, Kyle C. Smith. Modeling the Transient Effects of Pore-Scale Convection and Redox Reactions in the Pseudo-Steady Limit. Journal of The Electrochemical Society, 2019; 167 (1): 013521 DOI: 10.1149/2.0212001JES
Cite This Page:
| MLA | University of Illinois College of Engineering. "Theory of pore-scale transport to enable improved flow batteries." ScienceDaily. ScienceDaily, 21 November 2019. <www.sciencedaily.com/releases/2019/11/191121121749.htm>. |
| APA | University of Illinois College of Engineering. (2019, November 21). Theory of pore-scale transport to enable improved flow batteries. ScienceDaily. Retrieved November 21, 2019 from www.sciencedaily.com/releases/2019/11/191121121749.htm |
| Chicago | University of Illinois College of Engineering. "Theory of pore-scale transport to enable improved flow batteries." ScienceDaily. www.sciencedaily.com/releases/2019/11/191121121749.htm (accessed November 21, 2019). |


--- layout: post title: "I have the coolest wife..." date: 2011-10-01 18:12:45 +0000 permalink: /2011/10/01/i-have-the-coolest-wife/ category: Personal tags: - Life - Anniversary - Wife redirect_from: - /blog/i-have-the-coolest-wife/ ---
I have the coolest wife because, although today is our first anniversary, she not only allowed, but encouraged, me to attend DrupalCamp Atlanta. Hopefully I learn something useful. :)
I love her very much... and I'm not just saying that because she reads this blog.
(Oh, and don't worry, we'll be spending the evening together.)


[label] FCB expression[,expression,...,expression]
fcb $00
fcb $00,3,44,$33
fcb 5[$00] * Repeat byte $00 5 times fcb 10[$44,$11] * Repeat seq. $44,$11 10 times
| KASM | X |
| CCASM | X |
| OS-9 RMA | X |
| Edt/Asm III | X |
| Edtasm6309 | X |
| Disk Edtasm+ | X* |
| Edtasm+ | X* |
| Macro-80C | X |
*The stock versions of EDTASM+ and Disk EDTASM+ do not support multiple FCB expressions on a single line.


For holding raw data information of a data section defined in GDAQ system. This struct is used in binary data reading and data distribution, and holds one channel from an event in the binary file.
More...
#include <tEntry.h>
For holding raw data information of a data section defined in GDAQ system. This struct is used in binary data reading and data distribution, and holds one channel from an event in the binary file.
- Author
- SUN Yazhou, asia..nosp@m.rabb.nosp@m.it@16.nosp<EMAIL_ADDRESS>- Date
- Created: 2017/10/10 Last revised: 2018/5/26, SUN Yazhou.
- Copyright
- 2017-2018, SUN Yazhou.
◆ tEntry()
◆ initialize()
| void tEntry::initialize |
( |
| ) |
|
◆ show()
| void tEntry::show |
( |
| ) |
const |
◆ TOT()
| double tEntry::TOT |
( |
| ) |
const |
◆ TOT1()
| double tEntry::TOT1 |
( |
| ) |
const |
◆ bunchId
trigger time in one time cycle
◆ channelId
◆ index
◆ is_V
◆ leadingTime
| double tEntry::leadingTime[NMAX] |
◆ name
entry name, showing the identity of the entry
◆ nl
count of leading edges in one data section
◆ NMAX
| const int tEntry::NMAX = 10 |
|
static |
◆ nt
count of trailing edges in one dat section
◆ trailingTime
| double tEntry::trailingTime[NMAX] |
The documentation for this struct was generated from the following files:


January 2015 - October 2017 (2.7 years): Google - Site Reliability Engineer (Level 5)
I worked as a site reliability engineer on the systems that Google uses to crawl the web and to fetch latency sensitive web content for users. This involved reviewing designs for parts of the the system and working with developers and members of my team to ensure designs were robust, reliable, scalable, and monitorable with good visibility for troubleshooting problems, designing and implementing testing regimes, deployment systems, and monitoring systems along with day to day operations of the systems and being on call to fix or mitigate problems when incidents occurred.
April 1997 - September 2014 (17 years): Hewlett Packard (originally Compaq
Computer Corporation) Houston, TX -- Senior Systems Software Engineer
Since about 2002, I worked on the linux storage drivers for HP's Smart Array line of RAID controllers, first the "cciss" driver for which I added support for SCSI tape drives, and later the current "hpsa" driver. I am the primary author of the hpsa driver. I also worked on a SCSI-over-PCIE driver for about a year in collaboration with SanDisk which I presented at the 2013 Linux Storage Filesystem and Memory Management Summit.
I worked on enhancements to the hpsa driver to use the new (in 2014) SCSI multiqueue enhancements and remove all the locks from the main i/o path to enable performance of nearly 1 million IOPS on a single controller to a single logical drive. I have been invited to the Linux Storage Filesystem and Memory Management Summit in 2013 and 2014. Some of my linux kernel commits may be found here: https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/log/?qt=author&q=scameron
Additionally I worked on various Smart Array related storage utilities such as SNMP agents, array configuration utilities, smartmontools, and various other small utility programs.
In 2000, I worked on a driver for Smart Array RAID controllers for about a year for IBM's and SCO's Project Monterey, which was a unix derivative of SCO Unixware and IBM's AIX that was supposed to run on IBM POWER, PowerPC, IA64 and IA32 processors. Project Monterey didn't really go anywhere though, as linux kind of came along and ate its lunch.
From April 1997 to September 1998, I was responsible for supporting SCO Openserver on Compaq's "SmartStart" CD. The SmartStart CD contained a number of system specific drivers, most importantly storage drivers, and a modified version of SCO's install media to enable injecting those drivers during the install process.
During that time (1997-1998) I was also the system administrator for one of Compaq's source code servers, which contained all the source for the drivers and utilities that made up Compaq's drivers and software for SCO Openserver, Unixware 2, and Unixware 7. That entailed the usual backups, user administration, etc. Also, I set up and initiated the CVS source code control system then in use. Prior to my arrival they were using just RCS.
I also automated the build process, and incidentally this was how I got into driver development. Floppy diskette images needed to be created and Unixware lacked any block loop device, so I wrote a driver for one to avoid the time consuming and medium-error prone use of actual floppy diskettes.
July 1992 - April 1997 (5 years): McDonnell Douglas Corporation (now Boeing) 16055 Space Center Blvd, Houston TX, 77062-6208 -- Unix Systems Administrator/Programmer
Since April 1995 I was the primary system administrator for a network of approximately 60 Sun workstations (Sparc 5s, Sparc 20s, an Enterprise 3000 and an Enterprise 5000) running SunOS 4.x or Solaris 2.x and 3 HP-9000s running HP-UX 9.x. My responsibilities included hardware installation, OS installation, software installation, licensing and configuration management, backups, user account administration, network administration, and general troubleshooting to name a few. Probably the most impressive thing I did in the Sys Admin vein was a very elaborate NIS/amd automounter setup. Seeing as how this was 1995, and mostly SunOS/Solaris, you might say I was a "classically trained sysadmin".
Prior to taking on system administration duties I worked as an Ada/C/X/Motif/SQL programmer and my responsibilities included design, implementation, testing and documentation of an Ada interface to an Oracle database and VMS file system and various programs which used the interface. In a related project, I was responsible for porting a portion of a real-time simulation control program written in Ada from a VAX ELN environment to a DEC Alpha/OSF/1 (later Compaq Alpha/Tru64 Unix) environment. This involved writing Ada interfaces to many Unix system calls such as those dealing with semaphores, message queues, and signals to name a few.
May 1989 - Jan 1992 (during summers and Christmas break from school) Advanced Computing Solutions, Inc. (ACSI, later RealData, probably no longer exists.) Houston, TX Data Systems Engineer
My responsibilities included design, coding, and testing of various programs and components of ACSI's (pre-WWW) on-line real estate information service (Oracle based), including programs to estimate adjustments to real estate property values, programs to efficiently search large volumes of data (for instance, all the property tax records for Harris County TX, numbered in the millions (remember, this is circa 1989 when "millions" was a big number) and generate reports in ASCII, PostScript, and troff formats. In addition I worked on ACSI's Commercial Multiple Listings Service (CMLS) and the billing system for the CMLS. I also worked on the redesign and conversion of a nationwide security alarm monitoring system from COBOL to C. This involved writing several cooperating C programs which communicated with each other in nearly every way possible, via sockets, shared memory, semaphores, message queues and FIFOs. All that work was done on a combination of HW, Suns, Data Generals, Masscomps and some AT&T 386 boxes running some beta release of SVR4. Languages/Software used included C, ProC, Bourne shell, C shell, SQLplus, SQLreport, SQLForms (version 2.0 --gasp!) awk, and troff. This work was all done during summer and Christmas breaks between semesters while attending Texas A & M. (total: 14.5 months)
Jan 1987 - Jan 1989 Mitre Corp. Nassau Bay, TX -- Technical Aide
My responsibilities at Mitre included adding a sophisticated (for its time) user interface to a queueing analysis program written in Turbo Pascal on a DOS machine. The interface included pull-down menus, windows and a spreadsheet-like data entry module. I also extended the analysis portion of the program by adding two new types of queues. I was also responsible for conversion of a Space Station requirements database prototype from DBase III to Oracle. This involved teaching myself to be my own Oracle DBA, teaching myself C, and integrating the emacs editor into my application. I also created a C program (the 2nd I ever wrote, after "hello, world!" of course) to read raw DBase III files and produce output in a form importable by Oracle (SQL "insert" statements and SQL*plus "create table" statements) This work was done during summer and Christmas breaks between semesters while attending Texas A & M.
Other Interests:
In January of 2013 I founded the Houston Recreational Computer Programming
meetup and ran it until November of 2014, and was a co-organizer of the Houston
Game Developers Show and Tell meetup.
http://www.meetup.com/Houston-Recreational-Computer-Programming-Group/
http://www.meetup.com/Houston-Game-Devs-Show-and-Tell/
I was an active member of Houston's hackerspace, TX/RX Labs from 2010 until 2015. See: http://txrxlabs.org Occasionally I taught a 2-day "Intro to C programming" course and a 2-day "Intro to Linux Device Driver programming" course there.
I'm also currently working on an open source multiplayer starship bridge simulator called "Space Nerds In Space" in my spare time. http://smcameron.github.io/space-nerds-in-space/
I built a cyclekart, which is a little car that's part way between a go-kart
and and an art project.
In progress: https://www.youtube.com/watch?v=7ocrvACdmN8
Finished: http://imgur.com/a/dY7PB#0
In 2007, I wrote a video game called Word War vi similar to the old arcade game Defender with a "vi vs. Emacs" theme, and later helped modify it to run on a home-made openlase driven RGB laser projector. The game may be found here: http://smcameron.github.io/wordwarvi/, The music, sound effects and voiceover work is substantially my doing as well.
In 2014 I presented a technique I came up with for generating somewhat realistic looking gas giant planet graphics which looks better than anything else I've seen out there (better than what's in Elite: Dangerous, for example) http://smcameron.github.io/space-nerds-in-space/gaseous-giganticus-slides/slideshow.html
In 2014 I ported Kurt Spencer's OpenSimplex noise algorithm to C and in 2018 my port was incorporated into the Godot game engine. See https://www.patreon.com/posts/godot-engine-my-21539216
References available upon request.


{% extends "base.html" %} {% load static %} {% block title %}About - {% endblock title %} {% block content %}
The key idea underpinning the Web Lab is that when mathematical and computational models are being developed, a primary goal should be the continuous comparison of those models against experimental data. When computational models are being re-used in new studies, it is similarly important to check that they behave appropriately in the new situation to which you're applying them.
To achieve this goal, it's a pre-requisite to be able to replicate in-silico precisely the same protocols used in an experiment of interest. We are therefore developing a language for describing rich 'virtual experiment' protocols, and software for running these on compatible models. This website provides a front-end to a prototype of that language and software.
Please browse around and view the results of protocols encoded so far, run on a range of cell models. If you wish to evaluate your own models under these protocols, you will need to register for an account and have it approved by a site admin. By default your own models, protocols and experiments are private so that only you may view them. This can be altered to 'public' to publish them to the world. You can also add other users as collaborators so they can view them and add new versions.
Currently only trusted users may upload new protocols, but if you have one you'd like to add to the system, please do contact us.
The initial paper about the Web Lab was published in Biophysical Journal. A preprint of our next Web Lab paper sets out our plans for the next two years.
For more background on the 'Functional Curation' experiment execution software, our 2011 reference publication is a good place to start. We also have a paper on the underlying concept of virtual experiments (along with an open access preprint). Full details about the open source software implementing the back-end for this system can be found on the Chaste website.
The main features on our "to do" list include:
You can read more in a preprint of our next Web Lab paper. Please get in touch if you would like to join forces to help with any of these.
As well as the back-end simulation tool being open source, the code for this website is also available under the same open source licence. The experimental prototype incorporating parameter fitting can be found in the old ‘cardiac-fitting’ branch. All work on this next version of the Web Lab is taking place within the ModellingWebLab GitHub organisation.
We would welcome collaborations with any who would be interested in producing a similar resource for a different scientific domain. Equally, anyone interested in contributing new plugins for displaying or comparing results is encouraged to contact us.
We would like to thank Steve Niederer and the Noble modelling group for discussions on ways to test cell model behaviour. We gratefully acknowledge funding from the 2020 Science Programme and BBRSC. The functional curation back-end software is built on top of Chaste.
{% endblock content %}


|
NANO100_BSP V3.04.001
The Board Support Package for Nano100BN Series
|
Data Structures | |
| struct | PWM_Capture_T |
Macros | |
| #define | _PWM_Source_Clock 12000000 |
| #define | _PWM_Resolution 65536 |
| #define | _PWM_Prescale_Max 256 |
| #define | _PWM_Duty_Scale 100 |
| #define | _ADC_Clock 300000 |
| #define | SEG_A_ON PA2=0 |
| #define | SEG_B_ON PA3=0 |
| #define | SEG_C_ON PA4=0 |
| #define | SEG_D_ON PA5=0 |
| #define | SEG_E_ON PA6=0 |
| #define | SEG_F_ON PA7=0 |
| #define | SEG_G_ON PD6=0 |
| #define | SEG_H_ON PD7=0 |
| #define | SEG_CONTROL1_ON PD14=1 |
| #define | SEG_CONTROL2_ON PD15=1 |
| #define | SEG_A_OFF PA2=1 |
| #define | SEG_B_OFF PA3=1 |
| #define | SEG_C_OFF PA4=1 |
| #define | SEG_D_OFF PA5=1 |
| #define | SEG_E_OFF PA6=1 |
| #define | SEG_F_OFF PA7=1 |
| #define | SEG_G_OFF PD6=1 |
| #define | SEG_H_OFF PD7=1 |
| #define | SEG_CONTROL1_OFF PD14=0 |
| #define | SEG_CONTROL2_OFF PD15=0 |
| #define | KEY1_INPUT PD12 |
| #define | KEY2_INPUT PE12 |
| #define | KEY3_INPUT PD0 |
| #define | KEY4_INPUT PD1 |
| #define | Buzzer_Power_ON PE6=1 |
| Control Buzzer module power on. More... | |
| #define | Buzzer_Power_OFF PE6=0 |
| Control Buzzer module power down. More... | |
| #define | NEC_LDC_MARK 16 |
| #define | NEC_LDC_SPACE 8 |
| #define | NEC_BIT_MARK 1 |
| #define | NEC_ONE_SPACE 3 |
| #define | NEC_ZERO_SPACE 1 |
| #define | NEC_BYTES 4 |
| #define | LED1_ON PB0=0 |
| #define | LED2_ON PB1=0 |
| #define | LED3_ON PE9=0 |
| #define | LED4_ON PE10=0 |
| #define | LED5_ON PE11=0 |
| #define | LED6_ON PD8=0 |
| #define | LED7_ON PD9=0 |
| #define | LED8_ON PC7=0 |
| #define | LED1_OFF PB0=1 |
| #define | LED2_OFF PB1=1 |
| #define | LED3_OFF PE9=1 |
| #define | LED4_OFF PE10=1 |
| #define | LED5_OFF PE11=1 |
| #define | LED6_OFF PD8=1 |
| #define | LED7_OFF PD9=1 |
| #define | LED8_OFF PC7=1 |
Typedefs | |
| typedef void(* | IrDA_Code_Exe) (volatile uint8_t *IR_CODE) |
Enumerations | |
| enum | E_Edge { Rising = 0 , Falling = 1 } |
Functions | |
| void | Show_Seven_Segment (unsigned char no, unsigned char number) |
| This function turn on 7_Segment LED to show numbers. More... | |
| void | Close_Seven_Segment (void) |
| This function turn off 7_Segment LED. More... | |
| void | Open_Seven_Segment (void) |
| This function turn on 7_Segment LED. More... | |
| void | Initial_KEY_INPUT (void) |
| Set Button GPIO to input mode. More... | |
| unsigned char | Get_KEY_INPUT (void) |
| This function get button status. More... | |
| void | Open_Buzzer (void) |
| This function enable PWM1 module clock and set clock source to start Buzzer module. More... | |
| void | Close_Buzzer (void) |
| This function power down the Buzzer module. More... | |
| void | Write_Buzzer (unsigned int frequence, unsigned int duty) |
| This function set PWM output frequence and duty to drive Buzzer module. More... | |
| void | Open_CLK_OUT (uint32_t Clock_Source, uint32_t FRQDIV_FSEL) |
| This function enable frequency divider module clock, enable frequency divider clock function and configure frequency divider. More... | |
| void | Close_CLK_OUT (void) |
| This function disable frequency output function. More... | |
| void | I2C_EEPROM_Init (uint8_t u8Divider) |
| This function initializes the I2C module, bit-rate = 100 kHz and enable the corresponding interrupt. More... | |
| void | I2C_EEPROM_Write (uint16_t u16Address, uint8_t u8Data) |
| This function do the I2C data writing to EEPROM device. More... | |
| uint8_t | I2C_EEPROM_Read (uint16_t u16Address) |
| This function do the I2C data reading from EEPROM device. More... | |
| void | Open_EINT1 (void) |
| This function enables EINT1 interrupt and IRQ handler, and configs trigger condition for falling edge. More... | |
| void | SendNEC (uint8_t *data) |
| This function is used to transmit IrDA NEC waveform through PC 15 (PWM1_CH3) More... | |
| void | IrDA_NEC_TxRx_Init (IrDA_Code_Exe pfnIrDA_Code_Exe) |
| This function is used to initiate PWM for IrDA NEC. More... | |
| void | IrDa_NEC_Rx (uint32_t u32Time) |
| This function is used to detect NEC IR procotol. More... | |
| void | initial_led (void) |
| Set LED GPIO to output mode. More... | |
| void | LED_on (unsigned int temp) |
| This function turn on LED numbers to open or close. More... | |
| void | Open_PWM6_OUT (uint32_t PWM_Frequency, uint32_t PWM_Duty) |
| void | Close_PWM6_OUT (void) |
| void | Open_PWM7_Capture (void) |
| void | Close_PWM7_Capture (void) |
| void | Get_PWM7_Capture_Data (void) |
| void | Open_PWM3_Capture (void) |
| void | Close_PWM3_Capture (void) |
| void | Get_PWM3_Capture_Data (void) |
| void | Initial_PWM_DAC (void) |
| This function is used to setup multi-function pin of PC12 for PWM1_CH0. More... | |
| void | Write_PWMDAC (void) |
| This function is used to set PWM for PWM DAC. More... | |
| void | Initial_PWM_LED (void) |
| Set multi-function pins for PWM0 channel 0,1,2. More... | |
| void | PWM_LED (void) |
| Set PWM clock enable and HCLK as PWM clock source, PWM frequency is 100Hz, duty 30% and enable output of all PWM channels. More... | |
| void | Open_SPI_Flash (void) |
| Open GPIO port for SPI interface and configure this SPI controller as Master, MSB first, clock idle low, TX at falling-edge, RX at rising-edge, 32-bit length transaction, disable the automatic hardware slave select function and SPI serial clock rate = 2 MHz. More... | |
| unsigned int | SpiFlash_ReadMidDid (void) |
| Read back the Manufacturer ID and Device ID from SPI Flash device. More... | |
| void | SpiFlash_ChipErase (void) |
| This function do the chip erasing to SPI Flash device. More... | |
| unsigned int | SpiFlash_ReadStatusReg1 (void) |
| Read back the Status Register 1 from SPI Flash device. More... | |
| unsigned int | SpiFlash_ReadStatusReg2 (void) |
| Read back the Status Register 2 from SPI Flash device. More... | |
| void | SpiFlash_WaitReady (void) |
| Waiting for the BUSY bit of SPI Flash that be cleared to 0. More... | |
| void | SpiFlash_PageProgram (unsigned char *DataBuffer, unsigned int StartAddress, unsigned int ByteCount) |
| This function do the page programming to SPI Flash device. More... | |
| void | SpiFlash_ReadData (unsigned char *DataBuffer, unsigned int StartAddress, unsigned int ByteCount) |
| This function do the data reading from SPI Flash device. More... | |
| void | Init_PDMA_CH1_for_SPI0_TX (uint32_t u32SrcAddr) |
| This function initializes the PDMA channel 1 for SPI0 transmitting TX and the data that will be transmiitted out are stored in the source buffer. More... | |
| void | Init_PDMA_CH2_for_SPI0_RX (uint32_t u32DstAddr) |
| This function initializes the PDMA channel 2 for SPI0 receiving RX and the receiving data will be stored into the destination buffer. More... | |
| unsigned int | SpiFlash_w_PDMA_ReadMidDid (void) |
| Read back the Manufacturer ID and Device ID from SPI Flash device. More... | |
| void | SpiFlash_w_PDMA_ChipErase (void) |
| This function do the chip erasing to SPI Flash device. More... | |
| unsigned int | SpiFlash_w_PDMA_ReadStatusReg1 (void) |
| Read back the Status Register 1 from SPI Flash device. More... | |
| unsigned int | SpiFlash_w_PDMA_ReadStatusReg2 (void) |
| Read back the Status Register 2 from SPI Flash device. More... | |
| void | SpiFlash_w_PDMA_WaitReady (void) |
| Waiting for the BUSY bit of SPI Flash that be cleared to 0. More... | |
| void | SpiFlash_w_PDMA_PageProgram (unsigned int StartAddress, unsigned int ByteCount) |
| This function do the page programming to SPI Flash device. More... | |
| void | SpiFlash_w_PDMA_ReadData (unsigned int StartAddress, unsigned int ByteCount) |
| This function do the data reading from SPI Flash device. More... | |
| void | SYS_Init (void) |
| This function enables HXT, LXT and LIRC clock and sets HCLK source from HXT to 42MHz. More... | |
| void | Open_Threshold_Knob (void) |
| void | Close_Threshold_Knob (void) |
| uint32_t | Get_Threshold_Knob (void) |
| void | Initial_Timer_Outport (void) |
| void | initial_Timer_Toggle (void) |
| This function is enable TM2 toggle. More... | |
| void | UART0_Init (void) |
| Initiate UART0 as 8-N-1 and 115200 BPS. More... | |
| void | Open_Volume_Knob (void) |
| void | Close_Volume_Knob (void) |
| uint32_t | Get_Volume_Knob (void) |
| void | Initial_SEG_GPIO (void) |
| Set 7_Segment LED GPIO to output mode. More... | |
| void | Initial_PWM_GPIO (void) |
| This function config PC.13 multi-function for PWM to drive Buzzer module, and config PE.6 multi-function for GPIO to control Buzzer power. More... | |
| __INLINE void | I2C_PIN_Init (void) |
| Open GPIO port for I2C interface and enable this I2C controller clock and reset it. More... | |
| void | I2C1_IRQHandler (void) |
| I2C interrupt handler. Checks the I2C interrupt flag, clears the corresponding event flag and calls the related handler subroutine. More... | |
| void | I2C_MasterRx (uint32_t u32Status) |
| This function checks the status of I2C, sets the related control bit and data if needed when this I2C module is master receiver. More... | |
| void | I2C_MasterTx (uint32_t u32Status) |
| This function checks the status of I2C, sets the related control bit and data if needed when this I2C module is master transmitter. More... | |
| void | Initial_EINT1_GPIO (void) |
| This function initializes PB.15 multi-function for EINT1 to detect external interrupt. More... | |
| void | Mark (uint8_t N) |
| This function is used to transmit MASK waveform Pulse = 1/3 duty @38KHz frequency. More... | |
| void | SPACE (uint8_t N) |
| This function is used to transmit SPACE waveform. More... | |
| void | initial_close (void) |
| Set LED GPIO to input mode. More... | |
| void | PDMA_IRQHandler (void) |
| PDMA interrupt handler. Check the PDMA interrupt flag and clear the corresponding event flag. More... | |
| void | Initial_Timer_port (void) |
| This function is used to TM2 output and TMR3 capture function. More... | |
| void | initial_Timer_count (void) |
| This function is enable TM2 count. More... | |
| void | initial_Timer_capture (void) |
| This function is enable TM3 Capture. More... | |
Variables | |
| __IO uint32_t | PWM_Capture_T::Capture_Rising [2] |
| __IO uint32_t | PWM_Capture_T::Capture_Falling [2] |
| __IO uint32_t | PWM_Capture_T::Last_Edge |
| __IO uint32_t | PWM_Capture_T::High_Period |
| __IO uint32_t | PWM_Capture_T::Low_Period |
| __IO uint32_t | PWM_Capture_T::Signal_Period |
| __IO float | PWM_Capture_T::Signal_Frequency |
| uint32_t | PWM67_Clock |
| uint32_t | Open_PWM6_OUT_Fail |
| uint32_t | Open_PWM3_Capture_Fail |
| uint32_t | Open_PWM7_Capture_Fail |
| PWM_Capture_T | PWM3 |
| PWM_Capture_T | PWM7 |
| uint32_t | Open_Volume_Knob_Fail |
| #define _ADC_Clock 300000 |
Definition at line 27 of file NuEdu-Basic01_Volume_Knob.h.
| #define _PWM_Duty_Scale 100 |
Definition at line 28 of file NuEdu-Basic01_PWM_Capture.h.
| #define _PWM_Prescale_Max 256 |
Definition at line 27 of file NuEdu-Basic01_PWM_Capture.h.
| #define _PWM_Resolution 65536 |
Definition at line 26 of file NuEdu-Basic01_PWM_Capture.h.
| #define _PWM_Source_Clock 12000000 |
Definition at line 25 of file NuEdu-Basic01_PWM_Capture.h.
| #define Buzzer_Power_OFF PE6=0 |
Control Buzzer module power down.
Definition at line 29 of file NuEdu-Basic01_Buzzer.c.
| #define Buzzer_Power_ON PE6=1 |
Control Buzzer module power on.
Definition at line 28 of file NuEdu-Basic01_Buzzer.c.
| #define KEY1_INPUT PD12 |
GPIO PD12 for Button1
Definition at line 28 of file NuEdu-Basic01_Button.c.
| #define KEY2_INPUT PE12 |
GPIO PE12 for Button2
Definition at line 29 of file NuEdu-Basic01_Button.c.
| #define KEY3_INPUT PD0 |
GPIO PD0 for Button3
Definition at line 30 of file NuEdu-Basic01_Button.c.
| #define KEY4_INPUT PD1 |
GPIO PD1 for Button4
Definition at line 31 of file NuEdu-Basic01_Button.c.
| #define LED1_OFF PB0=1 |
Definition at line 40 of file NuEdu-Basic01_LED.c.
| #define LED1_ON PB0=0 |
Definition at line 31 of file NuEdu-Basic01_LED.c.
| #define LED2_OFF PB1=1 |
Definition at line 41 of file NuEdu-Basic01_LED.c.
| #define LED2_ON PB1=0 |
Definition at line 32 of file NuEdu-Basic01_LED.c.
| #define LED3_OFF PE9=1 |
Definition at line 42 of file NuEdu-Basic01_LED.c.
| #define LED3_ON PE9=0 |
Definition at line 33 of file NuEdu-Basic01_LED.c.
| #define LED4_OFF PE10=1 |
Definition at line 43 of file NuEdu-Basic01_LED.c.
| #define LED4_ON PE10=0 |
Definition at line 34 of file NuEdu-Basic01_LED.c.
| #define LED5_OFF PE11=1 |
Definition at line 44 of file NuEdu-Basic01_LED.c.
| #define LED5_ON PE11=0 |
Definition at line 35 of file NuEdu-Basic01_LED.c.
| #define LED6_OFF PD8=1 |
Definition at line 45 of file NuEdu-Basic01_LED.c.
| #define LED6_ON PD8=0 |
Definition at line 36 of file NuEdu-Basic01_LED.c.
| #define LED7_OFF PD9=1 |
Definition at line 46 of file NuEdu-Basic01_LED.c.
| #define LED7_ON PD9=0 |
Definition at line 37 of file NuEdu-Basic01_LED.c.
| #define LED8_OFF PC7=1 |
Definition at line 47 of file NuEdu-Basic01_LED.c.
| #define LED8_ON PC7=0 |
Definition at line 38 of file NuEdu-Basic01_LED.c.
| #define NEC_BIT_MARK 1 |
Definition at line 141 of file NuEdu-Basic01_IrDA_NEC.c.
| #define NEC_BYTES 4 |
Definition at line 144 of file NuEdu-Basic01_IrDA_NEC.c.
| #define NEC_LDC_MARK 16 |
Definition at line 139 of file NuEdu-Basic01_IrDA_NEC.c.
| #define NEC_LDC_SPACE 8 |
Definition at line 140 of file NuEdu-Basic01_IrDA_NEC.c.
| #define NEC_ONE_SPACE 3 |
Definition at line 142 of file NuEdu-Basic01_IrDA_NEC.c.
| #define NEC_ZERO_SPACE 1 |
Definition at line 143 of file NuEdu-Basic01_IrDA_NEC.c.
| #define SEG_A_OFF PA2=1 |
Turn off segment A
Definition at line 41 of file NuEdu-Basic01_7_Segment.c.
| #define SEG_A_ON PA2=0 |
Turn on segment A
Definition at line 30 of file NuEdu-Basic01_7_Segment.c.
| #define SEG_B_OFF PA3=1 |
Turn off segment B
Definition at line 42 of file NuEdu-Basic01_7_Segment.c.
| #define SEG_B_ON PA3=0 |
Turn on segment B
Definition at line 31 of file NuEdu-Basic01_7_Segment.c.
| #define SEG_C_OFF PA4=1 |
Turn off segment C
Definition at line 43 of file NuEdu-Basic01_7_Segment.c.
| #define SEG_C_ON PA4=0 |
Turn on segment C
Definition at line 32 of file NuEdu-Basic01_7_Segment.c.
| #define SEG_CONTROL1_OFF PD14=0 |
Turn off 7_segment1
Definition at line 49 of file NuEdu-Basic01_7_Segment.c.
| #define SEG_CONTROL1_ON PD14=1 |
Turn on 7_segment1
Definition at line 38 of file NuEdu-Basic01_7_Segment.c.
| #define SEG_CONTROL2_OFF PD15=0 |
Turn off 7_segment2
Definition at line 50 of file NuEdu-Basic01_7_Segment.c.
| #define SEG_CONTROL2_ON PD15=1 |
Turn on 7_segment2
Definition at line 39 of file NuEdu-Basic01_7_Segment.c.
| #define SEG_D_OFF PA5=1 |
Turn off segment D
Definition at line 44 of file NuEdu-Basic01_7_Segment.c.
| #define SEG_D_ON PA5=0 |
Turn on segment D
Definition at line 33 of file NuEdu-Basic01_7_Segment.c.
| #define SEG_E_OFF PA6=1 |
Turn off segment E
Definition at line 45 of file NuEdu-Basic01_7_Segment.c.
| #define SEG_E_ON PA6=0 |
Turn on segment E
Definition at line 34 of file NuEdu-Basic01_7_Segment.c.
| #define SEG_F_OFF PA7=1 |
Turn off segment F
Definition at line 46 of file NuEdu-Basic01_7_Segment.c.
| #define SEG_F_ON PA7=0 |
Turn on segment F
Definition at line 35 of file NuEdu-Basic01_7_Segment.c.
| #define SEG_G_OFF PD6=1 |
Turn off segment G
Definition at line 47 of file NuEdu-Basic01_7_Segment.c.
| #define SEG_G_ON PD6=0 |
Turn on segment G
Definition at line 36 of file NuEdu-Basic01_7_Segment.c.
| #define SEG_H_OFF PD7=1 |
Turn off segment H
Definition at line 48 of file NuEdu-Basic01_7_Segment.c.
| #define SEG_H_ON PD7=0 |
Turn on segment H
Definition at line 37 of file NuEdu-Basic01_7_Segment.c.
| typedef void(* IrDA_Code_Exe) (volatile uint8_t *IR_CODE) |
Definition at line 46 of file NuEdu-Basic01_IrDA_NEC.h.
| enum E_Edge |
| Enumerator | |
|---|---|
| Rising | |
| Falling |
Definition at line 41 of file NuEdu-Basic01_PWM_Capture.h.
| void Close_Buzzer | ( | void | ) |
This function power down the Buzzer module.
Definition at line 91 of file NuEdu-Basic01_Buzzer.c.
| void Close_CLK_OUT | ( | void | ) |
This function disable frequency output function.
Definition at line 73 of file NuEdu-Basic01_ClkOut.c.
| void Close_PWM3_Capture | ( | void | ) |
Definition at line 332 of file NuEdu-Basic01_PWM_Capture.c.
| void Close_PWM6_OUT | ( | void | ) |
Definition at line 113 of file NuEdu-Basic01_PWM_Capture.c.
| void Close_PWM7_Capture | ( | void | ) |
Definition at line 189 of file NuEdu-Basic01_PWM_Capture.c.
| void Close_Seven_Segment | ( | void | ) |
This function turn off 7_Segment LED.
Definition at line 93 of file NuEdu-Basic01_7_Segment.c.
| void Close_Threshold_Knob | ( | void | ) |
Definition at line 34 of file NuEdu-Basic01_Threshold_Knob.c.
| void Close_Volume_Knob | ( | void | ) |
| unsigned char Get_KEY_INPUT | ( | void | ) |
This function get button status.
Definition at line 48 of file NuEdu-Basic01_Button.c.
| void Get_PWM3_Capture_Data | ( | void | ) |
Definition at line 357 of file NuEdu-Basic01_PWM_Capture.c.
| void Get_PWM7_Capture_Data | ( | void | ) |
Definition at line 212 of file NuEdu-Basic01_PWM_Capture.c.
| uint32_t Get_Threshold_Knob | ( | void | ) |
Definition at line 62 of file NuEdu-Basic01_Threshold_Knob.c.
| uint32_t Get_Volume_Knob | ( | void | ) |
Definition at line 64 of file NuEdu-Basic01_ADC_Knob.c.
| void I2C1_IRQHandler | ( | void | ) |
I2C interrupt handler. Checks the I2C interrupt flag, clears the corresponding event flag and calls the related handler subroutine.
Definition at line 71 of file NuEdu-Basic01_I2C_EEPROM.c.
| void I2C_EEPROM_Init | ( | uint8_t | u8Divider | ) |
This function initializes the I2C module, bit-rate = 100 kHz and enable the corresponding interrupt.
| [in] | u8Divider | A divider of I2C clock source. |
Definition at line 99 of file NuEdu-Basic01_I2C_EEPROM.c.
| uint8_t I2C_EEPROM_Read | ( | uint16_t | u16Address | ) |
This function do the I2C data reading from EEPROM device.
| [in] | u16Address | An address of EEPROM that will be read. |
Definition at line 260 of file NuEdu-Basic01_I2C_EEPROM.c.
| void I2C_EEPROM_Write | ( | uint16_t | u16Address, |
| uint8_t | u8Data | ||
| ) |
This function do the I2C data writing to EEPROM device.
| [in] | u16Address | An address of EEPROM that will be written. |
| [in] | u18Data | The data will be written to EEPROM. |
Definition at line 234 of file NuEdu-Basic01_I2C_EEPROM.c.
| void I2C_MasterRx | ( | uint32_t | u32Status | ) |
This function checks the status of I2C, sets the related control bit and data if needed when this I2C module is master receiver.
| [in] | u32Status | The current value of I2C status register. |
Definition at line 121 of file NuEdu-Basic01_I2C_EEPROM.c.
| void I2C_MasterTx | ( | uint32_t | u32Status | ) |
This function checks the status of I2C, sets the related control bit and data if needed when this I2C module is master transmitter.
| [in] | u32Status | The current value of I2C status register. |
Definition at line 184 of file NuEdu-Basic01_I2C_EEPROM.c.
| __INLINE void I2C_PIN_Init | ( | void | ) |
Open GPIO port for I2C interface and enable this I2C controller clock and reset it.
Definition at line 52 of file NuEdu-Basic01_I2C_EEPROM.c.
| void Init_PDMA_CH1_for_SPI0_TX | ( | uint32_t | u32SrcAddr | ) |
This function initializes the PDMA channel 1 for SPI0 transmitting TX and the data that will be transmiitted out are stored in the source buffer.
| [in] | u32SrcAddr | A source address for the transmitting data buffer. |
Definition at line 117 of file NuEdu-Basic01_SPI_Flash_w_PDMA.c.
| void Init_PDMA_CH2_for_SPI0_RX | ( | uint32_t | u32DstAddr | ) |
This function initializes the PDMA channel 2 for SPI0 receiving RX and the receiving data will be stored into the destination buffer.
| [in] | u32DstAddr | A destination address for the receiving data buffer. |
Definition at line 163 of file NuEdu-Basic01_SPI_Flash_w_PDMA.c.
| void initial_close | ( | void | ) |
Set LED GPIO to input mode.
Definition at line 131 of file NuEdu-Basic01_LED.c.
| void Initial_EINT1_GPIO | ( | void | ) |
This function initializes PB.15 multi-function for EINT1 to detect external interrupt.
Definition at line 33 of file NuEdu-Basic01_Interrupt.c.
| void Initial_KEY_INPUT | ( | void | ) |
Set Button GPIO to input mode.
Definition at line 37 of file NuEdu-Basic01_Button.c.
| void initial_led | ( | void | ) |
Set LED GPIO to output mode.
Definition at line 54 of file NuEdu-Basic01_LED.c.
| void Initial_PWM_DAC | ( | void | ) |
This function is used to setup multi-function pin of PC12 for PWM1_CH0.
Definition at line 51 of file NuEdu-Basic01_PWMDAC.c.
| void Initial_PWM_GPIO | ( | void | ) |
This function config PC.13 multi-function for PWM to drive Buzzer module, and config PE.6 multi-function for GPIO to control Buzzer power.
Definition at line 42 of file NuEdu-Basic01_Buzzer.c.
| void Initial_PWM_LED | ( | void | ) |
Set multi-function pins for PWM0 channel 0,1,2.
Definition at line 33 of file NuEdu-Basic01_RGBLED.c.
| void Initial_SEG_GPIO | ( | void | ) |
Set 7_Segment LED GPIO to output mode.
Definition at line 56 of file NuEdu-Basic01_7_Segment.c.
| void initial_Timer_capture | ( | void | ) |
This function is enable TM3 Capture.
Definition at line 94 of file NuEdu-Basic01_Timer_Ouput_Capture.c.
| void initial_Timer_count | ( | void | ) |
This function is enable TM2 count.
Definition at line 72 of file NuEdu-Basic01_Timer_Ouput_Capture.c.
| void Initial_Timer_Outport | ( | void | ) |
| void Initial_Timer_port | ( | void | ) |
This function is used to TM2 output and TMR3 capture function.
Definition at line 31 of file NuEdu-Basic01_Timer_Ouput_Capture.c.
| void initial_Timer_Toggle | ( | void | ) |
This function is enable TM2 toggle.
Definition at line 49 of file NuEdu-Basic01_Timer_Ouput_Capture.c.
| void IrDa_NEC_Rx | ( | uint32_t | u32Time | ) |
This function is used to detect NEC IR procotol.
| [in] | u32Time | is the time length of received bit |
Definition at line 48 of file NuEdu-Basic01_IrDA_NEC.c.
| void IrDA_NEC_TxRx_Init | ( | IrDA_Code_Exe | pfnIrDA_Code_Exe | ) |
This function is used to initiate PWM for IrDA NEC.
| [in] | pfnIrDA_Code_Exe | is function pointer that will be executed after received IrDA NEC command |
Definition at line 206 of file NuEdu-Basic01_IrDA_NEC.c.
| void LED_on | ( | unsigned int | temp | ) |
This function turn on LED numbers to open or close.
| [in] | temp | Turn on which LED open number |
Definition at line 75 of file NuEdu-Basic01_LED.c.
| void Mark | ( | uint8_t | N | ) |
This function is used to transmit MASK waveform Pulse = 1/3 duty @38KHz frequency.
| [in] | N | is time length of MASK |
Definition at line 152 of file NuEdu-Basic01_IrDA_NEC.c.
| void Open_Buzzer | ( | void | ) |
This function enable PWM1 module clock and set clock source to start Buzzer module.
Definition at line 58 of file NuEdu-Basic01_Buzzer.c.
| void Open_CLK_OUT | ( | uint32_t | Clock_Source, |
| uint32_t | FRQDIV_FSEL | ||
| ) |
This function enable frequency divider module clock, enable frequency divider clock function and configure frequency divider.
| [in] | Clock_Source | is ClkOut function clock source |
| [in] | FRQDIV_FSEL | is divider output frequency selection |
Output selected clock to FCLKO. The output clock frequency is divided by FRQDIV_FSEL. The formula is: FCLKO frequency = (Clock_Source frequency) / 2^(FRQDIV_FSEL + 1)
Definition at line 44 of file NuEdu-Basic01_ClkOut.c.
| void Open_EINT1 | ( | void | ) |
This function enables EINT1 interrupt and IRQ handler, and configs trigger condition for falling edge.
Definition at line 46 of file NuEdu-Basic01_Interrupt.c.
| void Open_PWM3_Capture | ( | void | ) |
Definition at line 273 of file NuEdu-Basic01_PWM_Capture.c.
| void Open_PWM6_OUT | ( | uint32_t | PWM_Frequency, |
| uint32_t | PWM_Duty | ||
| ) |
Definition at line 25 of file NuEdu-Basic01_PWM_Capture.c.
| void Open_PWM7_Capture | ( | void | ) |
Definition at line 132 of file NuEdu-Basic01_PWM_Capture.c.
| void Open_Seven_Segment | ( | void | ) |
This function turn on 7_Segment LED.
Definition at line 76 of file NuEdu-Basic01_7_Segment.c.
| void Open_SPI_Flash | ( | void | ) |
Open GPIO port for SPI interface and configure this SPI controller as Master, MSB first, clock idle low, TX at falling-edge, RX at rising-edge, 32-bit length transaction, disable the automatic hardware slave select function and SPI serial clock rate = 2 MHz.
Definition at line 43 of file NuEdu-Basic01_SPI_Flash.c.
| void Open_Threshold_Knob | ( | void | ) |
Definition at line 5 of file NuEdu-Basic01_Threshold_Knob.c.
| void Open_Volume_Knob | ( | void | ) |
| void PDMA_IRQHandler | ( | void | ) |
PDMA interrupt handler. Check the PDMA interrupt flag and clear the corresponding event flag.
Definition at line 55 of file NuEdu-Basic01_SPI_Flash_w_PDMA.c.
| void PWM_LED | ( | void | ) |
Set PWM clock enable and HCLK as PWM clock source, PWM frequency is 100Hz, duty 30% and enable output of all PWM channels.
Definition at line 47 of file NuEdu-Basic01_RGBLED.c.
| void SendNEC | ( | uint8_t * | data | ) |
This function is used to transmit IrDA NEC waveform through PC 15 (PWM1_CH3)
| [in] | data | is pointer of trasnmitted data |
Definition at line 174 of file NuEdu-Basic01_IrDA_NEC.c.
| void Show_Seven_Segment | ( | unsigned char | no, |
| unsigned char | number | ||
| ) |
This function turn on 7_Segment LED to show numbers.
| [in] | no | Turn on which 7_Segment LED |
| [in] | number | 7_Segment LED show number 0~9 |
Definition at line 115 of file NuEdu-Basic01_7_Segment.c.
| void SPACE | ( | uint8_t | N | ) |
This function is used to transmit SPACE waveform.
| [in] | N | is time length of SPACE |
Definition at line 164 of file NuEdu-Basic01_IrDA_NEC.c.
| void SpiFlash_ChipErase | ( | void | ) |
This function do the chip erasing to SPI Flash device.
Definition at line 127 of file NuEdu-Basic01_SPI_Flash.c.
| void SpiFlash_PageProgram | ( | unsigned char * | DataBuffer, |
| unsigned int | StartAddress, | ||
| unsigned int | ByteCount | ||
| ) |
This function do the page programming to SPI Flash device.
| [in] | *DataBuffer | A Point that point to source data buffer. |
| [in] | StartAddress | A start address of SPI Flash that will be programmed. |
| [in] | ByteCount | Byte count number that will be programmed. |
Definition at line 261 of file NuEdu-Basic01_SPI_Flash.c.
| void SpiFlash_ReadData | ( | unsigned char * | DataBuffer, |
| unsigned int | StartAddress, | ||
| unsigned int | ByteCount | ||
| ) |
This function do the data reading from SPI Flash device.
| [in] | *DataBuffer | A Point that point to destination data buffer. |
| [in] | StartAddress | A start address of SPI Flash that will be read. |
| [in] | ByteCount | Byte count number that will be read. |
Definition at line 335 of file NuEdu-Basic01_SPI_Flash.c.
| unsigned int SpiFlash_ReadMidDid | ( | void | ) |
Read back the Manufacturer ID and Device ID from SPI Flash device.
Definition at line 71 of file NuEdu-Basic01_SPI_Flash.c.
| unsigned int SpiFlash_ReadStatusReg1 | ( | void | ) |
Read back the Status Register 1 from SPI Flash device.
Definition at line 169 of file NuEdu-Basic01_SPI_Flash.c.
| unsigned int SpiFlash_ReadStatusReg2 | ( | void | ) |
Read back the Status Register 2 from SPI Flash device.
Definition at line 203 of file NuEdu-Basic01_SPI_Flash.c.
| void SpiFlash_w_PDMA_ChipErase | ( | void | ) |
This function do the chip erasing to SPI Flash device.
Definition at line 264 of file NuEdu-Basic01_SPI_Flash_w_PDMA.c.
| void SpiFlash_w_PDMA_PageProgram | ( | unsigned int | StartAddress, |
| unsigned int | ByteCount | ||
| ) |
This function do the page programming to SPI Flash device.
| [in] | StartAddress | A start address of SPI Flash that will be programmed. |
| [in] | ByteCount | Byte count number that will be programmed. |
Definition at line 396 of file NuEdu-Basic01_SPI_Flash_w_PDMA.c.
| void SpiFlash_w_PDMA_ReadData | ( | unsigned int | StartAddress, |
| unsigned int | ByteCount | ||
| ) |
This function do the data reading from SPI Flash device.
| [in] | StartAddress | A start address of SPI Flash that will be read. |
| [in] | ByteCount | Byte count number that will be read. |
Definition at line 473 of file NuEdu-Basic01_SPI_Flash_w_PDMA.c.
| unsigned int SpiFlash_w_PDMA_ReadMidDid | ( | void | ) |
Read back the Manufacturer ID and Device ID from SPI Flash device.
Definition at line 208 of file NuEdu-Basic01_SPI_Flash_w_PDMA.c.
| unsigned int SpiFlash_w_PDMA_ReadStatusReg1 | ( | void | ) |
Read back the Status Register 1 from SPI Flash device.
Definition at line 306 of file NuEdu-Basic01_SPI_Flash_w_PDMA.c.
| unsigned int SpiFlash_w_PDMA_ReadStatusReg2 | ( | void | ) |
Read back the Status Register 2 from SPI Flash device.
Definition at line 340 of file NuEdu-Basic01_SPI_Flash_w_PDMA.c.
| void SpiFlash_w_PDMA_WaitReady | ( | void | ) |
Waiting for the BUSY bit of SPI Flash that be cleared to 0.
Definition at line 374 of file NuEdu-Basic01_SPI_Flash_w_PDMA.c.
| void SpiFlash_WaitReady | ( | void | ) |
Waiting for the BUSY bit of SPI Flash that be cleared to 0.
Definition at line 237 of file NuEdu-Basic01_SPI_Flash.c.
| void SYS_Init | ( | void | ) |
This function enables HXT, LXT and LIRC clock and sets HCLK source from HXT to 42MHz.
Definition at line 37 of file NuEdu-Basic01_System.c.
| void UART0_Init | ( | void | ) |
Initiate UART0 as 8-N-1 and 115200 BPS.
Definition at line 34 of file NuEdu-Basic01_UART.c.
| void Write_Buzzer | ( | unsigned int | frequence, |
| unsigned int | duty | ||
| ) |
This function set PWM output frequence and duty to drive Buzzer module.
Definition at line 78 of file NuEdu-Basic01_Buzzer.c.
| void Write_PWMDAC | ( | void | ) |
This function is used to set PWM for PWM DAC.
Definition at line 33 of file NuEdu-Basic01_PWMDAC.c.
| __IO uint32_t PWM_Capture_T::Capture_Falling[2] |
Definition at line 33 of file NuEdu-Basic01_PWM_Capture.h.
| __IO uint32_t PWM_Capture_T::Capture_Rising[2] |
Definition at line 32 of file NuEdu-Basic01_PWM_Capture.h.
| __IO uint32_t PWM_Capture_T::High_Period |
Definition at line 35 of file NuEdu-Basic01_PWM_Capture.h.
| __IO uint32_t PWM_Capture_T::Last_Edge |
Definition at line 34 of file NuEdu-Basic01_PWM_Capture.h.
| __IO uint32_t PWM_Capture_T::Low_Period |
Definition at line 36 of file NuEdu-Basic01_PWM_Capture.h.
|
extern |
Definition at line 19 of file NuEdu-Basic01_PWM_Capture.c.
|
extern |
Definition at line 18 of file NuEdu-Basic01_PWM_Capture.c.
|
extern |
Definition at line 20 of file NuEdu-Basic01_PWM_Capture.c.
|
extern |
Definition at line 7 of file NuEdu-Basic01_ADC_Knob.c.
|
extern |
Definition at line 22 of file NuEdu-Basic01_PWM_Capture.c.
|
extern |
Definition at line 17 of file NuEdu-Basic01_PWM_Capture.c.
|
extern |
Definition at line 23 of file NuEdu-Basic01_PWM_Capture.c.
| __IO float PWM_Capture_T::Signal_Frequency |
Definition at line 38 of file NuEdu-Basic01_PWM_Capture.h.
| __IO uint32_t PWM_Capture_T::Signal_Period |
Definition at line 37 of file NuEdu-Basic01_PWM_Capture.h.


based on https://github.com/mwolicki/brainfuck_rust; source code https://github.com/mwolicki/brainfuck_rust_web